Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,117 @@
# SPDX-License-Identifier: GPL-2.0
if SOC_RENESAS
menu "Renesas PM Domains"
# SoC Family
config SYSC_RCAR
bool "System Controller support for R-Car" if COMPILE_TEST
config SYSC_RCAR_GEN4
bool "System Controller support for R-Car Gen4" if COMPILE_TEST
config SYSC_RMOBILE
bool "System Controller support for R-Mobile" if COMPILE_TEST
# SoC
config SYSC_R8A7742
bool "System Controller support for R8A7742 (RZ/G1H)" if COMPILE_TEST
select SYSC_RCAR
config SYSC_R8A7743
bool "System Controller support for R8A7743 (RZ/G1M)" if COMPILE_TEST
select SYSC_RCAR
config SYSC_R8A7745
bool "System Controller support for R8A7745 (RZ/G1E)" if COMPILE_TEST
select SYSC_RCAR
config SYSC_R8A77470
bool "System Controller support for R8A77470 (RZ/G1C)" if COMPILE_TEST
select SYSC_RCAR
config SYSC_R8A774A1
bool "System Controller support for R8A774A1 (RZ/G2M)" if COMPILE_TEST
select SYSC_RCAR
config SYSC_R8A774B1
bool "System Controller support for R8A774B1 (RZ/G2N)" if COMPILE_TEST
select SYSC_RCAR
config SYSC_R8A774C0
bool "System Controller support for R8A774C0 (RZ/G2E)" if COMPILE_TEST
select SYSC_RCAR
config SYSC_R8A774E1
bool "System Controller support for R8A774E1 (RZ/G2H)" if COMPILE_TEST
select SYSC_RCAR
config SYSC_R8A7779
bool "System Controller support for R8A7779 (R-Car H1)" if COMPILE_TEST
select SYSC_RCAR
config SYSC_R8A7790
bool "System Controller support for R8A7790 (R-Car H2)" if COMPILE_TEST
select SYSC_RCAR
config SYSC_R8A7791
bool "System Controller support for R8A7791/R8A7793 (R-Car M2-W/N)" if COMPILE_TEST
select SYSC_RCAR
config SYSC_R8A7792
bool "System Controller support for R8A7792 (R-Car V2H)" if COMPILE_TEST
select SYSC_RCAR
config SYSC_R8A7794
bool "System Controller support for R8A7794 (R-Car E2)" if COMPILE_TEST
select SYSC_RCAR
config SYSC_R8A7795
bool "System Controller support for R8A7795 (R-Car H3)" if COMPILE_TEST
select SYSC_RCAR
config SYSC_R8A77960
bool "System Controller support for R8A77960 (R-Car M3-W)" if COMPILE_TEST
select SYSC_RCAR
config SYSC_R8A77961
bool "System Controller support for R8A77961 (R-Car M3-W+)" if COMPILE_TEST
select SYSC_RCAR
config SYSC_R8A77965
bool "System Controller support for R8A77965 (R-Car M3-N)" if COMPILE_TEST
select SYSC_RCAR
config SYSC_R8A77970
bool "System Controller support for R8A77970 (R-Car V3M)" if COMPILE_TEST
select SYSC_RCAR
config SYSC_R8A77980
bool "System Controller support for R8A77980 (R-Car V3H)" if COMPILE_TEST
select SYSC_RCAR
config SYSC_R8A77990
bool "System Controller support for R8A77990 (R-Car E3)" if COMPILE_TEST
select SYSC_RCAR
config SYSC_R8A77995
bool "System Controller support for R8A77995 (R-Car D3)" if COMPILE_TEST
select SYSC_RCAR
config SYSC_R8A779A0
bool "System Controller support for R8A779A0 (R-Car V3U)" if COMPILE_TEST
select SYSC_RCAR_GEN4
config SYSC_R8A779F0
bool "System Controller support for R8A779F0 (R-Car S4-8)" if COMPILE_TEST
select SYSC_RCAR_GEN4
config SYSC_R8A779G0
bool "System Controller support for R8A779G0 (R-Car V4H)" if COMPILE_TEST
select SYSC_RCAR_GEN4
config SYSC_R8A779H0
bool "System Controller support for R8A779H0 (R-Car V4M)" if COMPILE_TEST
select SYSC_RCAR_GEN4
endmenu
endif
@@ -0,0 +1,31 @@
# SPDX-License-Identifier: GPL-2.0
# SoC
obj-$(CONFIG_SYSC_R8A7742) += r8a7742-sysc.o
obj-$(CONFIG_SYSC_R8A7743) += r8a7743-sysc.o
obj-$(CONFIG_SYSC_R8A7745) += r8a7745-sysc.o
obj-$(CONFIG_SYSC_R8A77470) += r8a77470-sysc.o
obj-$(CONFIG_SYSC_R8A774A1) += r8a774a1-sysc.o
obj-$(CONFIG_SYSC_R8A774B1) += r8a774b1-sysc.o
obj-$(CONFIG_SYSC_R8A774C0) += r8a774c0-sysc.o
obj-$(CONFIG_SYSC_R8A774E1) += r8a774e1-sysc.o
obj-$(CONFIG_SYSC_R8A7779) += r8a7779-sysc.o
obj-$(CONFIG_SYSC_R8A7790) += r8a7790-sysc.o
obj-$(CONFIG_SYSC_R8A7791) += r8a7791-sysc.o
obj-$(CONFIG_SYSC_R8A7792) += r8a7792-sysc.o
obj-$(CONFIG_SYSC_R8A7794) += r8a7794-sysc.o
obj-$(CONFIG_SYSC_R8A7795) += r8a7795-sysc.o
obj-$(CONFIG_SYSC_R8A77960) += r8a77960-sysc.o
obj-$(CONFIG_SYSC_R8A77961) += r8a77961-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_R8A77990) += r8a77990-sysc.o
obj-$(CONFIG_SYSC_R8A77995) += r8a77995-sysc.o
obj-$(CONFIG_SYSC_R8A779A0) += r8a779a0-sysc.o
obj-$(CONFIG_SYSC_R8A779F0) += r8a779f0-sysc.o
obj-$(CONFIG_SYSC_R8A779G0) += r8a779g0-sysc.o
obj-$(CONFIG_SYSC_R8A779H0) += r8a779h0-sysc.o
# Family
obj-$(CONFIG_SYSC_RCAR) += rcar-sysc.o
obj-$(CONFIG_SYSC_RCAR_GEN4) += rcar-gen4-sysc.o
obj-$(CONFIG_SYSC_RMOBILE) += rmobile-sysc.o
@@ -0,0 +1,42 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Renesas RZ/G1H System Controller
*
* Copyright (C) 2020 Renesas Electronics Corp.
*/
#include <linux/kernel.h>
#include <dt-bindings/power/r8a7742-sysc.h>
#include "rcar-sysc.h"
static const struct rcar_sysc_area r8a7742_areas[] __initconst = {
{ "always-on", 0, 0, R8A7742_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
{ "ca15-scu", 0x180, 0, R8A7742_PD_CA15_SCU, R8A7742_PD_ALWAYS_ON,
PD_SCU },
{ "ca15-cpu0", 0x40, 0, R8A7742_PD_CA15_CPU0, R8A7742_PD_CA15_SCU,
PD_CPU_NOCR },
{ "ca15-cpu1", 0x40, 1, R8A7742_PD_CA15_CPU1, R8A7742_PD_CA15_SCU,
PD_CPU_NOCR },
{ "ca15-cpu2", 0x40, 2, R8A7742_PD_CA15_CPU2, R8A7742_PD_CA15_SCU,
PD_CPU_NOCR },
{ "ca15-cpu3", 0x40, 3, R8A7742_PD_CA15_CPU3, R8A7742_PD_CA15_SCU,
PD_CPU_NOCR },
{ "ca7-scu", 0x100, 0, R8A7742_PD_CA7_SCU, R8A7742_PD_ALWAYS_ON,
PD_SCU },
{ "ca7-cpu0", 0x1c0, 0, R8A7742_PD_CA7_CPU0, R8A7742_PD_CA7_SCU,
PD_CPU_NOCR },
{ "ca7-cpu1", 0x1c0, 1, R8A7742_PD_CA7_CPU1, R8A7742_PD_CA7_SCU,
PD_CPU_NOCR },
{ "ca7-cpu2", 0x1c0, 2, R8A7742_PD_CA7_CPU2, R8A7742_PD_CA7_SCU,
PD_CPU_NOCR },
{ "ca7-cpu3", 0x1c0, 3, R8A7742_PD_CA7_CPU3, R8A7742_PD_CA7_SCU,
PD_CPU_NOCR },
{ "rgx", 0xc0, 0, R8A7742_PD_RGX, R8A7742_PD_ALWAYS_ON },
};
const struct rcar_sysc_info r8a7742_sysc_info __initconst = {
.areas = r8a7742_areas,
.num_areas = ARRAY_SIZE(r8a7742_areas),
};
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Renesas RZ/G1M System Controller
*
* Copyright (C) 2016 Cogent Embedded Inc.
*/
#include <linux/kernel.h>
#include <dt-bindings/power/r8a7743-sysc.h>
#include "rcar-sysc.h"
static const struct rcar_sysc_area r8a7743_areas[] __initconst = {
{ "always-on", 0, 0, R8A7743_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
{ "ca15-scu", 0x180, 0, R8A7743_PD_CA15_SCU, R8A7743_PD_ALWAYS_ON,
PD_SCU },
{ "ca15-cpu0", 0x40, 0, R8A7743_PD_CA15_CPU0, R8A7743_PD_CA15_SCU,
PD_CPU_NOCR },
{ "ca15-cpu1", 0x40, 1, R8A7743_PD_CA15_CPU1, R8A7743_PD_CA15_SCU,
PD_CPU_NOCR },
{ "sgx", 0xc0, 0, R8A7743_PD_SGX, R8A7743_PD_ALWAYS_ON },
};
const struct rcar_sysc_info r8a7743_sysc_info __initconst = {
.areas = r8a7743_areas,
.num_areas = ARRAY_SIZE(r8a7743_areas),
};
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Renesas RZ/G1E System Controller
*
* Copyright (C) 2016 Cogent Embedded Inc.
*/
#include <linux/kernel.h>
#include <dt-bindings/power/r8a7745-sysc.h>
#include "rcar-sysc.h"
static const struct rcar_sysc_area r8a7745_areas[] __initconst = {
{ "always-on", 0, 0, R8A7745_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
{ "ca7-scu", 0x100, 0, R8A7745_PD_CA7_SCU, R8A7745_PD_ALWAYS_ON,
PD_SCU },
{ "ca7-cpu0", 0x1c0, 0, R8A7745_PD_CA7_CPU0, R8A7745_PD_CA7_SCU,
PD_CPU_NOCR },
{ "ca7-cpu1", 0x1c0, 1, R8A7745_PD_CA7_CPU1, R8A7745_PD_CA7_SCU,
PD_CPU_NOCR },
{ "sgx", 0xc0, 0, R8A7745_PD_SGX, R8A7745_PD_ALWAYS_ON },
};
const struct rcar_sysc_info r8a7745_sysc_info __initconst = {
.areas = r8a7745_areas,
.num_areas = ARRAY_SIZE(r8a7745_areas),
};
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Renesas RZ/G1C System Controller
*
* Copyright (C) 2018 Renesas Electronics Corp.
*/
#include <linux/kernel.h>
#include <dt-bindings/power/r8a77470-sysc.h>
#include "rcar-sysc.h"
static const struct rcar_sysc_area r8a77470_areas[] __initconst = {
{ "always-on", 0, 0, R8A77470_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
{ "ca7-scu", 0x100, 0, R8A77470_PD_CA7_SCU, R8A77470_PD_ALWAYS_ON,
PD_SCU },
{ "ca7-cpu0", 0x1c0, 0, R8A77470_PD_CA7_CPU0, R8A77470_PD_CA7_SCU,
PD_CPU_NOCR },
{ "ca7-cpu1", 0x1c0, 1, R8A77470_PD_CA7_CPU1, R8A77470_PD_CA7_SCU,
PD_CPU_NOCR },
{ "sgx", 0xc0, 0, R8A77470_PD_SGX, R8A77470_PD_ALWAYS_ON },
};
const struct rcar_sysc_info r8a77470_sysc_info __initconst = {
.areas = r8a77470_areas,
.num_areas = ARRAY_SIZE(r8a77470_areas),
};
@@ -0,0 +1,44 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Renesas RZ/G2M System Controller
* Copyright (C) 2018 Renesas Electronics Corp.
*
* Based on Renesas R-Car M3-W System Controller
* Copyright (C) 2016 Glider bvba
*/
#include <linux/kernel.h>
#include <dt-bindings/power/r8a774a1-sysc.h>
#include "rcar-sysc.h"
static const struct rcar_sysc_area r8a774a1_areas[] __initconst = {
{ "always-on", 0, 0, R8A774A1_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
{ "ca57-scu", 0x1c0, 0, R8A774A1_PD_CA57_SCU, R8A774A1_PD_ALWAYS_ON,
PD_SCU },
{ "ca57-cpu0", 0x80, 0, R8A774A1_PD_CA57_CPU0, R8A774A1_PD_CA57_SCU,
PD_CPU_NOCR },
{ "ca57-cpu1", 0x80, 1, R8A774A1_PD_CA57_CPU1, R8A774A1_PD_CA57_SCU,
PD_CPU_NOCR },
{ "ca53-scu", 0x140, 0, R8A774A1_PD_CA53_SCU, R8A774A1_PD_ALWAYS_ON,
PD_SCU },
{ "ca53-cpu0", 0x200, 0, R8A774A1_PD_CA53_CPU0, R8A774A1_PD_CA53_SCU,
PD_CPU_NOCR },
{ "ca53-cpu1", 0x200, 1, R8A774A1_PD_CA53_CPU1, R8A774A1_PD_CA53_SCU,
PD_CPU_NOCR },
{ "ca53-cpu2", 0x200, 2, R8A774A1_PD_CA53_CPU2, R8A774A1_PD_CA53_SCU,
PD_CPU_NOCR },
{ "ca53-cpu3", 0x200, 3, R8A774A1_PD_CA53_CPU3, R8A774A1_PD_CA53_SCU,
PD_CPU_NOCR },
{ "a3vc", 0x380, 0, R8A774A1_PD_A3VC, R8A774A1_PD_ALWAYS_ON },
{ "a2vc0", 0x3c0, 0, R8A774A1_PD_A2VC0, R8A774A1_PD_A3VC },
{ "a2vc1", 0x3c0, 1, R8A774A1_PD_A2VC1, R8A774A1_PD_A3VC },
{ "3dg-a", 0x100, 0, R8A774A1_PD_3DG_A, R8A774A1_PD_ALWAYS_ON },
{ "3dg-b", 0x100, 1, R8A774A1_PD_3DG_B, R8A774A1_PD_3DG_A },
};
const struct rcar_sysc_info r8a774a1_sysc_info __initconst = {
.areas = r8a774a1_areas,
.num_areas = ARRAY_SIZE(r8a774a1_areas),
};
@@ -0,0 +1,37 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Renesas RZ/G2N System Controller
* Copyright (C) 2019 Renesas Electronics Corp.
*
* Based on Renesas R-Car M3-W System Controller
* Copyright (C) 2016 Glider bvba
*/
#include <linux/bits.h>
#include <linux/kernel.h>
#include <dt-bindings/power/r8a774b1-sysc.h>
#include "rcar-sysc.h"
static const struct rcar_sysc_area r8a774b1_areas[] __initconst = {
{ "always-on", 0, 0, R8A774B1_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
{ "ca57-scu", 0x1c0, 0, R8A774B1_PD_CA57_SCU, R8A774B1_PD_ALWAYS_ON,
PD_SCU },
{ "ca57-cpu0", 0x80, 0, R8A774B1_PD_CA57_CPU0, R8A774B1_PD_CA57_SCU,
PD_CPU_NOCR },
{ "ca57-cpu1", 0x80, 1, R8A774B1_PD_CA57_CPU1, R8A774B1_PD_CA57_SCU,
PD_CPU_NOCR },
{ "a3vc", 0x380, 0, R8A774B1_PD_A3VC, R8A774B1_PD_ALWAYS_ON },
{ "a3vp", 0x340, 0, R8A774B1_PD_A3VP, R8A774B1_PD_ALWAYS_ON },
{ "a2vc1", 0x3c0, 1, R8A774B1_PD_A2VC1, R8A774B1_PD_A3VC },
{ "3dg-a", 0x100, 0, R8A774B1_PD_3DG_A, R8A774B1_PD_ALWAYS_ON },
{ "3dg-b", 0x100, 1, R8A774B1_PD_3DG_B, R8A774B1_PD_3DG_A },
};
const struct rcar_sysc_info r8a774b1_sysc_info __initconst = {
.areas = r8a774b1_areas,
.num_areas = ARRAY_SIZE(r8a774b1_areas),
.extmask_offs = 0x2f8,
.extmask_val = BIT(0),
};
@@ -0,0 +1,55 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Renesas RZ/G2E System Controller
* Copyright (C) 2018 Renesas Electronics Corp.
*
* Based on Renesas R-Car E3 System Controller
*/
#include <linux/bits.h>
#include <linux/kernel.h>
#include <linux/sys_soc.h>
#include <dt-bindings/power/r8a774c0-sysc.h>
#include "rcar-sysc.h"
static struct rcar_sysc_area r8a774c0_areas[] __initdata = {
{ "always-on", 0, 0, R8A774C0_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
{ "ca53-scu", 0x140, 0, R8A774C0_PD_CA53_SCU, R8A774C0_PD_ALWAYS_ON,
PD_SCU },
{ "ca53-cpu0", 0x200, 0, R8A774C0_PD_CA53_CPU0, R8A774C0_PD_CA53_SCU,
PD_CPU_NOCR },
{ "ca53-cpu1", 0x200, 1, R8A774C0_PD_CA53_CPU1, R8A774C0_PD_CA53_SCU,
PD_CPU_NOCR },
{ "a3vc", 0x380, 0, R8A774C0_PD_A3VC, R8A774C0_PD_ALWAYS_ON },
{ "a2vc1", 0x3c0, 1, R8A774C0_PD_A2VC1, R8A774C0_PD_A3VC },
{ "3dg-a", 0x100, 0, R8A774C0_PD_3DG_A, R8A774C0_PD_ALWAYS_ON },
{ "3dg-b", 0x100, 1, R8A774C0_PD_3DG_B, R8A774C0_PD_3DG_A },
};
/* Fixups for RZ/G2E ES1.0 revision */
static const struct soc_device_attribute r8a774c0[] __initconst = {
{ .soc_id = "r8a774c0", .revision = "ES1.0" },
{ /* sentinel */ }
};
static int __init r8a774c0_sysc_init(void)
{
if (soc_device_match(r8a774c0)) {
/* Fix incorrect 3DG hierarchy */
swap(r8a774c0_areas[6], r8a774c0_areas[7]);
r8a774c0_areas[6].parent = R8A774C0_PD_ALWAYS_ON;
r8a774c0_areas[7].parent = R8A774C0_PD_3DG_B;
}
return 0;
}
const struct rcar_sysc_info r8a774c0_sysc_info __initconst = {
.init = r8a774c0_sysc_init,
.areas = r8a774c0_areas,
.num_areas = ARRAY_SIZE(r8a774c0_areas),
.extmask_offs = 0x2f8,
.extmask_val = BIT(0),
};
@@ -0,0 +1,43 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Renesas RZ/G2H System Controller
* Copyright (C) 2020 Renesas Electronics Corp.
*
* Based on Renesas R-Car H3 System Controller
* Copyright (C) 2016-2017 Glider bvba
*/
#include <linux/kernel.h>
#include <dt-bindings/power/r8a774e1-sysc.h>
#include "rcar-sysc.h"
static const struct rcar_sysc_area r8a774e1_areas[] __initconst = {
{ "always-on", 0, 0, R8A774E1_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
{ "ca57-scu", 0x1c0, 0, R8A774E1_PD_CA57_SCU, R8A774E1_PD_ALWAYS_ON, PD_SCU },
{ "ca57-cpu0", 0x80, 0, R8A774E1_PD_CA57_CPU0, R8A774E1_PD_CA57_SCU, PD_CPU_NOCR },
{ "ca57-cpu1", 0x80, 1, R8A774E1_PD_CA57_CPU1, R8A774E1_PD_CA57_SCU, PD_CPU_NOCR },
{ "ca57-cpu2", 0x80, 2, R8A774E1_PD_CA57_CPU2, R8A774E1_PD_CA57_SCU, PD_CPU_NOCR },
{ "ca57-cpu3", 0x80, 3, R8A774E1_PD_CA57_CPU3, R8A774E1_PD_CA57_SCU, PD_CPU_NOCR },
{ "ca53-scu", 0x140, 0, R8A774E1_PD_CA53_SCU, R8A774E1_PD_ALWAYS_ON, PD_SCU },
{ "ca53-cpu0", 0x200, 0, R8A774E1_PD_CA53_CPU0, R8A774E1_PD_CA53_SCU, PD_CPU_NOCR },
{ "ca53-cpu1", 0x200, 1, R8A774E1_PD_CA53_CPU1, R8A774E1_PD_CA53_SCU, PD_CPU_NOCR },
{ "ca53-cpu2", 0x200, 2, R8A774E1_PD_CA53_CPU2, R8A774E1_PD_CA53_SCU, PD_CPU_NOCR },
{ "ca53-cpu3", 0x200, 3, R8A774E1_PD_CA53_CPU3, R8A774E1_PD_CA53_SCU, PD_CPU_NOCR },
{ "a3vp", 0x340, 0, R8A774E1_PD_A3VP, R8A774E1_PD_ALWAYS_ON },
{ "a3vc", 0x380, 0, R8A774E1_PD_A3VC, R8A774E1_PD_ALWAYS_ON },
{ "a2vc1", 0x3c0, 1, R8A774E1_PD_A2VC1, R8A774E1_PD_A3VC },
{ "3dg-a", 0x100, 0, R8A774E1_PD_3DG_A, R8A774E1_PD_ALWAYS_ON },
{ "3dg-b", 0x100, 1, R8A774E1_PD_3DG_B, R8A774E1_PD_3DG_A },
{ "3dg-c", 0x100, 2, R8A774E1_PD_3DG_C, R8A774E1_PD_3DG_B },
{ "3dg-d", 0x100, 3, R8A774E1_PD_3DG_D, R8A774E1_PD_3DG_C },
{ "3dg-e", 0x100, 4, R8A774E1_PD_3DG_E, R8A774E1_PD_3DG_D },
};
const struct rcar_sysc_info r8a774e1_sysc_info __initconst = {
.areas = r8a774e1_areas,
.num_areas = ARRAY_SIZE(r8a774e1_areas),
.extmask_offs = 0x2f8,
.extmask_val = BIT(0),
};
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Renesas R-Car H1 System Controller
*
* Copyright (C) 2016 Glider bvba
*/
#include <linux/kernel.h>
#include <dt-bindings/power/r8a7779-sysc.h>
#include "rcar-sysc.h"
static const struct rcar_sysc_area r8a7779_areas[] __initconst = {
{ "always-on", 0, 0, R8A7779_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
{ "arm1", 0x40, 1, R8A7779_PD_ARM1, R8A7779_PD_ALWAYS_ON,
PD_CPU_CR },
{ "arm2", 0x40, 2, R8A7779_PD_ARM2, R8A7779_PD_ALWAYS_ON,
PD_CPU_CR },
{ "arm3", 0x40, 3, R8A7779_PD_ARM3, R8A7779_PD_ALWAYS_ON,
PD_CPU_CR },
{ "sgx", 0xc0, 0, R8A7779_PD_SGX, R8A7779_PD_ALWAYS_ON },
{ "vdp", 0x100, 0, R8A7779_PD_VDP, R8A7779_PD_ALWAYS_ON },
{ "imp", 0x140, 0, R8A7779_PD_IMP, R8A7779_PD_ALWAYS_ON },
};
const struct rcar_sysc_info r8a7779_sysc_info __initconst = {
.areas = r8a7779_areas,
.num_areas = ARRAY_SIZE(r8a7779_areas),
};
@@ -0,0 +1,44 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Renesas R-Car H2 System Controller
*
* Copyright (C) 2016 Glider bvba
*/
#include <linux/kernel.h>
#include <dt-bindings/power/r8a7790-sysc.h>
#include "rcar-sysc.h"
static const struct rcar_sysc_area r8a7790_areas[] __initconst = {
{ "always-on", 0, 0, R8A7790_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
{ "ca15-scu", 0x180, 0, R8A7790_PD_CA15_SCU, R8A7790_PD_ALWAYS_ON,
PD_SCU },
{ "ca15-cpu0", 0x40, 0, R8A7790_PD_CA15_CPU0, R8A7790_PD_CA15_SCU,
PD_CPU_NOCR },
{ "ca15-cpu1", 0x40, 1, R8A7790_PD_CA15_CPU1, R8A7790_PD_CA15_SCU,
PD_CPU_NOCR },
{ "ca15-cpu2", 0x40, 2, R8A7790_PD_CA15_CPU2, R8A7790_PD_CA15_SCU,
PD_CPU_NOCR },
{ "ca15-cpu3", 0x40, 3, R8A7790_PD_CA15_CPU3, R8A7790_PD_CA15_SCU,
PD_CPU_NOCR },
{ "ca7-scu", 0x100, 0, R8A7790_PD_CA7_SCU, R8A7790_PD_ALWAYS_ON,
PD_SCU },
{ "ca7-cpu0", 0x1c0, 0, R8A7790_PD_CA7_CPU0, R8A7790_PD_CA7_SCU,
PD_CPU_NOCR },
{ "ca7-cpu1", 0x1c0, 1, R8A7790_PD_CA7_CPU1, R8A7790_PD_CA7_SCU,
PD_CPU_NOCR },
{ "ca7-cpu2", 0x1c0, 2, R8A7790_PD_CA7_CPU2, R8A7790_PD_CA7_SCU,
PD_CPU_NOCR },
{ "ca7-cpu3", 0x1c0, 3, R8A7790_PD_CA7_CPU3, R8A7790_PD_CA7_SCU,
PD_CPU_NOCR },
{ "sh-4a", 0x80, 0, R8A7790_PD_SH_4A, R8A7790_PD_ALWAYS_ON },
{ "rgx", 0xc0, 0, R8A7790_PD_RGX, R8A7790_PD_ALWAYS_ON },
{ "imp", 0x140, 0, R8A7790_PD_IMP, R8A7790_PD_ALWAYS_ON },
};
const struct rcar_sysc_info r8a7790_sysc_info __initconst = {
.areas = r8a7790_areas,
.num_areas = ARRAY_SIZE(r8a7790_areas),
};
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Renesas R-Car M2-W/N System Controller
*
* Copyright (C) 2016 Glider bvba
*/
#include <linux/kernel.h>
#include <dt-bindings/power/r8a7791-sysc.h>
#include "rcar-sysc.h"
static const struct rcar_sysc_area r8a7791_areas[] __initconst = {
{ "always-on", 0, 0, R8A7791_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
{ "ca15-scu", 0x180, 0, R8A7791_PD_CA15_SCU, R8A7791_PD_ALWAYS_ON,
PD_SCU },
{ "ca15-cpu0", 0x40, 0, R8A7791_PD_CA15_CPU0, R8A7791_PD_CA15_SCU,
PD_CPU_NOCR },
{ "ca15-cpu1", 0x40, 1, R8A7791_PD_CA15_CPU1, R8A7791_PD_CA15_SCU,
PD_CPU_NOCR },
{ "sh-4a", 0x80, 0, R8A7791_PD_SH_4A, R8A7791_PD_ALWAYS_ON },
{ "sgx", 0xc0, 0, R8A7791_PD_SGX, R8A7791_PD_ALWAYS_ON },
};
const struct rcar_sysc_info r8a7791_sysc_info __initconst = {
.areas = r8a7791_areas,
.num_areas = ARRAY_SIZE(r8a7791_areas),
};
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Renesas R-Car V2H (R8A7792) System Controller
*
* Copyright (C) 2016 Cogent Embedded Inc.
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <dt-bindings/power/r8a7792-sysc.h>
#include "rcar-sysc.h"
static const struct rcar_sysc_area r8a7792_areas[] __initconst = {
{ "always-on", 0, 0, R8A7792_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
{ "ca15-scu", 0x180, 0, R8A7792_PD_CA15_SCU, R8A7792_PD_ALWAYS_ON,
PD_SCU },
{ "ca15-cpu0", 0x40, 0, R8A7792_PD_CA15_CPU0, R8A7792_PD_CA15_SCU,
PD_CPU_NOCR },
{ "ca15-cpu1", 0x40, 1, R8A7792_PD_CA15_CPU1, R8A7792_PD_CA15_SCU,
PD_CPU_NOCR },
{ "sgx", 0xc0, 0, R8A7792_PD_SGX, R8A7792_PD_ALWAYS_ON },
{ "imp", 0x140, 0, R8A7792_PD_IMP, R8A7792_PD_ALWAYS_ON },
};
const struct rcar_sysc_info r8a7792_sysc_info __initconst = {
.areas = r8a7792_areas,
.num_areas = ARRAY_SIZE(r8a7792_areas),
};
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Renesas R-Car E2 System Controller
*
* Copyright (C) 2016 Glider bvba
*/
#include <linux/kernel.h>
#include <dt-bindings/power/r8a7794-sysc.h>
#include "rcar-sysc.h"
static const struct rcar_sysc_area r8a7794_areas[] __initconst = {
{ "always-on", 0, 0, R8A7794_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
{ "ca7-scu", 0x100, 0, R8A7794_PD_CA7_SCU, R8A7794_PD_ALWAYS_ON,
PD_SCU },
{ "ca7-cpu0", 0x1c0, 0, R8A7794_PD_CA7_CPU0, R8A7794_PD_CA7_SCU,
PD_CPU_NOCR },
{ "ca7-cpu1", 0x1c0, 1, R8A7794_PD_CA7_CPU1, R8A7794_PD_CA7_SCU,
PD_CPU_NOCR },
{ "sh-4a", 0x80, 0, R8A7794_PD_SH_4A, R8A7794_PD_ALWAYS_ON },
{ "sgx", 0xc0, 0, R8A7794_PD_SGX, R8A7794_PD_ALWAYS_ON },
};
const struct rcar_sysc_info r8a7794_sysc_info __initconst = {
.areas = r8a7794_areas,
.num_areas = ARRAY_SIZE(r8a7794_areas),
};
@@ -0,0 +1,86 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Renesas R-Car H3 System Controller
*
* Copyright (C) 2016-2017 Glider bvba
*/
#include <linux/bits.h>
#include <linux/kernel.h>
#include <linux/sys_soc.h>
#include <dt-bindings/power/r8a7795-sysc.h>
#include "rcar-sysc.h"
static struct rcar_sysc_area r8a7795_areas[] __initdata = {
{ "always-on", 0, 0, R8A7795_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
{ "ca57-scu", 0x1c0, 0, R8A7795_PD_CA57_SCU, R8A7795_PD_ALWAYS_ON,
PD_SCU },
{ "ca57-cpu0", 0x80, 0, R8A7795_PD_CA57_CPU0, R8A7795_PD_CA57_SCU,
PD_CPU_NOCR },
{ "ca57-cpu1", 0x80, 1, R8A7795_PD_CA57_CPU1, R8A7795_PD_CA57_SCU,
PD_CPU_NOCR },
{ "ca57-cpu2", 0x80, 2, R8A7795_PD_CA57_CPU2, R8A7795_PD_CA57_SCU,
PD_CPU_NOCR },
{ "ca57-cpu3", 0x80, 3, R8A7795_PD_CA57_CPU3, R8A7795_PD_CA57_SCU,
PD_CPU_NOCR },
{ "ca53-scu", 0x140, 0, R8A7795_PD_CA53_SCU, R8A7795_PD_ALWAYS_ON,
PD_SCU },
{ "ca53-cpu0", 0x200, 0, R8A7795_PD_CA53_CPU0, R8A7795_PD_CA53_SCU,
PD_CPU_NOCR },
{ "ca53-cpu1", 0x200, 1, R8A7795_PD_CA53_CPU1, R8A7795_PD_CA53_SCU,
PD_CPU_NOCR },
{ "ca53-cpu2", 0x200, 2, R8A7795_PD_CA53_CPU2, R8A7795_PD_CA53_SCU,
PD_CPU_NOCR },
{ "ca53-cpu3", 0x200, 3, R8A7795_PD_CA53_CPU3, R8A7795_PD_CA53_SCU,
PD_CPU_NOCR },
{ "a3vp", 0x340, 0, R8A7795_PD_A3VP, R8A7795_PD_ALWAYS_ON },
{ "cr7", 0x240, 0, R8A7795_PD_CR7, R8A7795_PD_ALWAYS_ON },
{ "a3vc", 0x380, 0, R8A7795_PD_A3VC, R8A7795_PD_ALWAYS_ON },
{ "a2vc1", 0x3c0, 1, R8A7795_PD_A2VC1, R8A7795_PD_A3VC },
{ "3dg-a", 0x100, 0, R8A7795_PD_3DG_A, R8A7795_PD_ALWAYS_ON },
{ "3dg-b", 0x100, 1, R8A7795_PD_3DG_B, R8A7795_PD_3DG_A },
{ "3dg-c", 0x100, 2, R8A7795_PD_3DG_C, R8A7795_PD_3DG_B },
{ "3dg-d", 0x100, 3, R8A7795_PD_3DG_D, R8A7795_PD_3DG_C },
{ "3dg-e", 0x100, 4, R8A7795_PD_3DG_E, R8A7795_PD_3DG_D },
{ "a3ir", 0x180, 0, R8A7795_PD_A3IR, R8A7795_PD_ALWAYS_ON },
};
/*
* Fixups for R-Car H3 revisions
*/
#define NO_EXTMASK BIT(1) /* Missing SYSCEXTMASK register */
static const struct soc_device_attribute r8a7795_quirks_match[] __initconst = {
{
.soc_id = "r8a7795", .revision = "ES2.*",
.data = (void *)(NO_EXTMASK),
},
{ /* sentinel */ }
};
static int __init r8a7795_sysc_init(void)
{
const struct soc_device_attribute *attr;
u32 quirks = 0;
attr = soc_device_match(r8a7795_quirks_match);
if (attr)
quirks = (uintptr_t)attr->data;
if (quirks & NO_EXTMASK)
r8a7795_sysc_info.extmask_val = 0;
return 0;
}
struct rcar_sysc_info r8a7795_sysc_info __initdata = {
.init = r8a7795_sysc_init,
.areas = r8a7795_areas,
.num_areas = ARRAY_SIZE(r8a7795_areas),
.extmask_offs = 0x2f8,
.extmask_val = BIT(0),
};
@@ -0,0 +1,49 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Renesas R-Car M3-W System Controller
*
* Copyright (C) 2016 Glider bvba
* Copyright (C) 2018-2019 Renesas Electronics Corporation
*/
#include <linux/bits.h>
#include <linux/kernel.h>
#include <dt-bindings/power/r8a7796-sysc.h>
#include "rcar-sysc.h"
static const struct rcar_sysc_area r8a77960_areas[] __initconst = {
{ "always-on", 0, 0, R8A7796_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
{ "ca57-scu", 0x1c0, 0, R8A7796_PD_CA57_SCU, R8A7796_PD_ALWAYS_ON,
PD_SCU },
{ "ca57-cpu0", 0x80, 0, R8A7796_PD_CA57_CPU0, R8A7796_PD_CA57_SCU,
PD_CPU_NOCR },
{ "ca57-cpu1", 0x80, 1, R8A7796_PD_CA57_CPU1, R8A7796_PD_CA57_SCU,
PD_CPU_NOCR },
{ "ca53-scu", 0x140, 0, R8A7796_PD_CA53_SCU, R8A7796_PD_ALWAYS_ON,
PD_SCU },
{ "ca53-cpu0", 0x200, 0, R8A7796_PD_CA53_CPU0, R8A7796_PD_CA53_SCU,
PD_CPU_NOCR },
{ "ca53-cpu1", 0x200, 1, R8A7796_PD_CA53_CPU1, R8A7796_PD_CA53_SCU,
PD_CPU_NOCR },
{ "ca53-cpu2", 0x200, 2, R8A7796_PD_CA53_CPU2, R8A7796_PD_CA53_SCU,
PD_CPU_NOCR },
{ "ca53-cpu3", 0x200, 3, R8A7796_PD_CA53_CPU3, R8A7796_PD_CA53_SCU,
PD_CPU_NOCR },
{ "cr7", 0x240, 0, R8A7796_PD_CR7, R8A7796_PD_ALWAYS_ON },
{ "a3vc", 0x380, 0, R8A7796_PD_A3VC, R8A7796_PD_ALWAYS_ON,
PD_OFF_DELAY },
{ "a2vc0", 0x3c0, 0, R8A7796_PD_A2VC0, R8A7796_PD_A3VC },
{ "a2vc1", 0x3c0, 1, R8A7796_PD_A2VC1, R8A7796_PD_A3VC },
{ "3dg-a", 0x100, 0, R8A7796_PD_3DG_A, R8A7796_PD_ALWAYS_ON },
{ "3dg-b", 0x100, 1, R8A7796_PD_3DG_B, R8A7796_PD_3DG_A },
{ "a3ir", 0x180, 0, R8A7796_PD_A3IR, R8A7796_PD_ALWAYS_ON,
PD_OFF_DELAY },
};
const struct rcar_sysc_info r8a77960_sysc_info __initconst = {
.areas = r8a77960_areas,
.num_areas = ARRAY_SIZE(r8a77960_areas),
};
@@ -0,0 +1,47 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Renesas R-Car M3-W+ System Controller
*
* Copyright (C) 2016 Glider bvba
* Copyright (C) 2018-2019 Renesas Electronics Corporation
*/
#include <linux/bits.h>
#include <linux/kernel.h>
#include <dt-bindings/power/r8a7796-sysc.h>
#include "rcar-sysc.h"
static const struct rcar_sysc_area r8a77961_areas[] __initconst = {
{ "always-on", 0, 0, R8A7796_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
{ "ca57-scu", 0x1c0, 0, R8A7796_PD_CA57_SCU, R8A7796_PD_ALWAYS_ON,
PD_SCU },
{ "ca57-cpu0", 0x80, 0, R8A7796_PD_CA57_CPU0, R8A7796_PD_CA57_SCU,
PD_CPU_NOCR },
{ "ca57-cpu1", 0x80, 1, R8A7796_PD_CA57_CPU1, R8A7796_PD_CA57_SCU,
PD_CPU_NOCR },
{ "ca53-scu", 0x140, 0, R8A7796_PD_CA53_SCU, R8A7796_PD_ALWAYS_ON,
PD_SCU },
{ "ca53-cpu0", 0x200, 0, R8A7796_PD_CA53_CPU0, R8A7796_PD_CA53_SCU,
PD_CPU_NOCR },
{ "ca53-cpu1", 0x200, 1, R8A7796_PD_CA53_CPU1, R8A7796_PD_CA53_SCU,
PD_CPU_NOCR },
{ "ca53-cpu2", 0x200, 2, R8A7796_PD_CA53_CPU2, R8A7796_PD_CA53_SCU,
PD_CPU_NOCR },
{ "ca53-cpu3", 0x200, 3, R8A7796_PD_CA53_CPU3, R8A7796_PD_CA53_SCU,
PD_CPU_NOCR },
{ "cr7", 0x240, 0, R8A7796_PD_CR7, R8A7796_PD_ALWAYS_ON },
{ "a3vc", 0x380, 0, R8A7796_PD_A3VC, R8A7796_PD_ALWAYS_ON },
{ "a2vc1", 0x3c0, 1, R8A7796_PD_A2VC1, R8A7796_PD_A3VC },
{ "3dg-a", 0x100, 0, R8A7796_PD_3DG_A, R8A7796_PD_ALWAYS_ON },
{ "3dg-b", 0x100, 1, R8A7796_PD_3DG_B, R8A7796_PD_3DG_A },
{ "a3ir", 0x180, 0, R8A7796_PD_A3IR, R8A7796_PD_ALWAYS_ON },
};
const struct rcar_sysc_info r8a77961_sysc_info __initconst = {
.areas = r8a77961_areas,
.num_areas = ARRAY_SIZE(r8a77961_areas),
.extmask_offs = 0x2f8,
.extmask_val = BIT(0),
};
@@ -0,0 +1,38 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Renesas R-Car M3-N System Controller
* Copyright (C) 2018 Jacopo Mondi <jacopo+renesas@jmondi.org>
*
* Based on Renesas R-Car M3-W System Controller
* Copyright (C) 2016 Glider bvba
*/
#include <linux/bits.h>
#include <linux/kernel.h>
#include <dt-bindings/power/r8a77965-sysc.h>
#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 },
};
const struct rcar_sysc_info r8a77965_sysc_info __initconst = {
.areas = r8a77965_areas,
.num_areas = ARRAY_SIZE(r8a77965_areas),
.extmask_offs = 0x2f8,
.extmask_val = BIT(0),
};
@@ -0,0 +1,37 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Renesas R-Car V3M System Controller
*
* Copyright (C) 2017 Cogent Embedded Inc.
*/
#include <linux/bits.h>
#include <linux/kernel.h>
#include <dt-bindings/power/r8a77970-sysc.h>
#include "rcar-sysc.h"
static const struct rcar_sysc_area r8a77970_areas[] __initconst = {
{ "always-on", 0, 0, R8A77970_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
{ "ca53-scu", 0x140, 0, R8A77970_PD_CA53_SCU, R8A77970_PD_ALWAYS_ON,
PD_SCU },
{ "ca53-cpu0", 0x200, 0, R8A77970_PD_CA53_CPU0, R8A77970_PD_CA53_SCU,
PD_CPU_NOCR },
{ "ca53-cpu1", 0x200, 1, R8A77970_PD_CA53_CPU1, R8A77970_PD_CA53_SCU,
PD_CPU_NOCR },
{ "a3ir", 0x180, 0, R8A77970_PD_A3IR, R8A77970_PD_ALWAYS_ON },
{ "a2ir0", 0x400, 0, R8A77970_PD_A2IR0, R8A77970_PD_A3IR },
{ "a2ir1", 0x400, 1, R8A77970_PD_A2IR1, R8A77970_PD_A3IR },
{ "a2dp", 0x400, 2, R8A77970_PD_A2DP, R8A77970_PD_A3IR },
{ "a2cn", 0x400, 3, R8A77970_PD_A2CN, 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 = {
.areas = r8a77970_areas,
.num_areas = ARRAY_SIZE(r8a77970_areas),
.extmask_offs = 0x1b0,
.extmask_val = BIT(0),
};
@@ -0,0 +1,55 @@
// 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 <linux/bits.h>
#include <linux/kernel.h>
#include <dt-bindings/power/r8a77980-sysc.h>
#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,
PD_CPU_NOCR },
{ "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 },
{ "a2dp0", 0x400, 11, R8A77980_PD_A2DP0, R8A77980_PD_A3IR },
{ "a2dp1", 0x400, 12, R8A77980_PD_A2DP1, R8A77980_PD_A3IR },
{ "a2cn", 0x400, 13, R8A77980_PD_A2CN, R8A77980_PD_A3IR },
{ "a3vip0", 0x2c0, 0, R8A77980_PD_A3VIP0, R8A77980_PD_ALWAYS_ON },
{ "a3vip1", 0x300, 0, R8A77980_PD_A3VIP1, R8A77980_PD_ALWAYS_ON },
{ "a3vip2", 0x280, 0, R8A77980_PD_A3VIP2, R8A77980_PD_ALWAYS_ON },
};
const struct rcar_sysc_info r8a77980_sysc_info __initconst = {
.areas = r8a77980_areas,
.num_areas = ARRAY_SIZE(r8a77980_areas),
.extmask_offs = 0x138,
.extmask_val = BIT(0),
};
@@ -0,0 +1,55 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Renesas R-Car E3 System Controller
*
* Copyright (C) 2018 Renesas Electronics Corp.
*/
#include <linux/bits.h>
#include <linux/kernel.h>
#include <linux/sys_soc.h>
#include <dt-bindings/power/r8a77990-sysc.h>
#include "rcar-sysc.h"
static struct rcar_sysc_area r8a77990_areas[] __initdata = {
{ "always-on", 0, 0, R8A77990_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
{ "ca53-scu", 0x140, 0, R8A77990_PD_CA53_SCU, R8A77990_PD_ALWAYS_ON,
PD_SCU },
{ "ca53-cpu0", 0x200, 0, R8A77990_PD_CA53_CPU0, R8A77990_PD_CA53_SCU,
PD_CPU_NOCR },
{ "ca53-cpu1", 0x200, 1, R8A77990_PD_CA53_CPU1, R8A77990_PD_CA53_SCU,
PD_CPU_NOCR },
{ "cr7", 0x240, 0, R8A77990_PD_CR7, R8A77990_PD_ALWAYS_ON },
{ "a3vc", 0x380, 0, R8A77990_PD_A3VC, R8A77990_PD_ALWAYS_ON },
{ "a2vc1", 0x3c0, 1, R8A77990_PD_A2VC1, R8A77990_PD_A3VC },
{ "3dg-a", 0x100, 0, R8A77990_PD_3DG_A, R8A77990_PD_ALWAYS_ON },
{ "3dg-b", 0x100, 1, R8A77990_PD_3DG_B, R8A77990_PD_3DG_A },
};
/* Fixups for R-Car E3 ES1.0 revision */
static const struct soc_device_attribute r8a77990[] __initconst = {
{ .soc_id = "r8a77990", .revision = "ES1.0" },
{ /* sentinel */ }
};
static int __init r8a77990_sysc_init(void)
{
if (soc_device_match(r8a77990)) {
/* Fix incorrect 3DG hierarchy */
swap(r8a77990_areas[7], r8a77990_areas[8]);
r8a77990_areas[7].parent = R8A77990_PD_ALWAYS_ON;
r8a77990_areas[8].parent = R8A77990_PD_3DG_B;
}
return 0;
}
const struct rcar_sysc_info r8a77990_sysc_info __initconst = {
.init = r8a77990_sysc_init,
.areas = r8a77990_areas,
.num_areas = ARRAY_SIZE(r8a77990_areas),
.extmask_offs = 0x2f8,
.extmask_val = BIT(0),
};
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Renesas R-Car D3 System Controller
*
* Copyright (C) 2017 Glider bvba
*/
#include <linux/kernel.h>
#include <dt-bindings/power/r8a77995-sysc.h>
#include "rcar-sysc.h"
static const struct rcar_sysc_area r8a77995_areas[] __initconst = {
{ "always-on", 0, 0, R8A77995_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
{ "ca53-scu", 0x140, 0, R8A77995_PD_CA53_SCU, R8A77995_PD_ALWAYS_ON,
PD_SCU },
{ "ca53-cpu0", 0x200, 0, R8A77995_PD_CA53_CPU0, R8A77995_PD_CA53_SCU,
PD_CPU_NOCR },
};
const struct rcar_sysc_info r8a77995_sysc_info __initconst = {
.areas = r8a77995_areas,
.num_areas = ARRAY_SIZE(r8a77995_areas),
};
@@ -0,0 +1,64 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Renesas R-Car V3U System Controller
*
* Copyright (C) 2020 Renesas Electronics Corp.
*/
#include <linux/kernel.h>
#include <dt-bindings/power/r8a779a0-sysc.h>
#include "rcar-gen4-sysc.h"
static struct rcar_gen4_sysc_area r8a779a0_areas[] __initdata = {
{ "always-on", R8A779A0_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
{ "a3e0", R8A779A0_PD_A3E0, R8A779A0_PD_ALWAYS_ON, PD_SCU },
{ "a3e1", R8A779A0_PD_A3E1, R8A779A0_PD_ALWAYS_ON, PD_SCU },
{ "a2e0d0", R8A779A0_PD_A2E0D0, R8A779A0_PD_A3E0, PD_SCU },
{ "a2e0d1", R8A779A0_PD_A2E0D1, R8A779A0_PD_A3E0, PD_SCU },
{ "a2e1d0", R8A779A0_PD_A2E1D0, R8A779A0_PD_A3E1, PD_SCU },
{ "a2e1d1", R8A779A0_PD_A2E1D1, R8A779A0_PD_A3E1, PD_SCU },
{ "a1e0d0c0", R8A779A0_PD_A1E0D0C0, R8A779A0_PD_A2E0D0, PD_CPU_NOCR },
{ "a1e0d0c1", R8A779A0_PD_A1E0D0C1, R8A779A0_PD_A2E0D0, PD_CPU_NOCR },
{ "a1e0d1c0", R8A779A0_PD_A1E0D1C0, R8A779A0_PD_A2E0D1, PD_CPU_NOCR },
{ "a1e0d1c1", R8A779A0_PD_A1E0D1C1, R8A779A0_PD_A2E0D1, PD_CPU_NOCR },
{ "a1e1d0c0", R8A779A0_PD_A1E1D0C0, R8A779A0_PD_A2E1D0, PD_CPU_NOCR },
{ "a1e1d0c1", R8A779A0_PD_A1E1D0C1, R8A779A0_PD_A2E1D0, PD_CPU_NOCR },
{ "a1e1d1c0", R8A779A0_PD_A1E1D1C0, R8A779A0_PD_A2E1D1, PD_CPU_NOCR },
{ "a1e1d1c1", R8A779A0_PD_A1E1D1C1, R8A779A0_PD_A2E1D1, PD_CPU_NOCR },
{ "3dg-a", R8A779A0_PD_3DG_A, R8A779A0_PD_ALWAYS_ON },
{ "3dg-b", R8A779A0_PD_3DG_B, R8A779A0_PD_3DG_A },
{ "a3vip0", R8A779A0_PD_A3VIP0, R8A779A0_PD_ALWAYS_ON },
{ "a3vip1", R8A779A0_PD_A3VIP1, R8A779A0_PD_ALWAYS_ON },
{ "a3vip3", R8A779A0_PD_A3VIP3, R8A779A0_PD_ALWAYS_ON },
{ "a3vip2", R8A779A0_PD_A3VIP2, R8A779A0_PD_ALWAYS_ON },
{ "a3isp01", R8A779A0_PD_A3ISP01, R8A779A0_PD_ALWAYS_ON },
{ "a3isp23", R8A779A0_PD_A3ISP23, R8A779A0_PD_ALWAYS_ON },
{ "a3ir", R8A779A0_PD_A3IR, R8A779A0_PD_ALWAYS_ON },
{ "a2cn0", R8A779A0_PD_A2CN0, R8A779A0_PD_A3IR },
{ "a2imp01", R8A779A0_PD_A2IMP01, R8A779A0_PD_A3IR },
{ "a2dp0", R8A779A0_PD_A2DP0, R8A779A0_PD_A3IR },
{ "a2cv0", R8A779A0_PD_A2CV0, R8A779A0_PD_A3IR },
{ "a2cv1", R8A779A0_PD_A2CV1, R8A779A0_PD_A3IR },
{ "a2cv4", R8A779A0_PD_A2CV4, R8A779A0_PD_A3IR },
{ "a2cv6", R8A779A0_PD_A2CV6, R8A779A0_PD_A3IR },
{ "a2cn2", R8A779A0_PD_A2CN2, R8A779A0_PD_A3IR },
{ "a2imp23", R8A779A0_PD_A2IMP23, R8A779A0_PD_A3IR },
{ "a2dp1", R8A779A0_PD_A2DP1, R8A779A0_PD_A3IR },
{ "a2cv2", R8A779A0_PD_A2CV2, R8A779A0_PD_A3IR },
{ "a2cv3", R8A779A0_PD_A2CV3, R8A779A0_PD_A3IR },
{ "a2cv5", R8A779A0_PD_A2CV5, R8A779A0_PD_A3IR },
{ "a2cv7", R8A779A0_PD_A2CV7, R8A779A0_PD_A3IR },
{ "a2cn1", R8A779A0_PD_A2CN1, R8A779A0_PD_A3IR },
{ "a1cnn0", R8A779A0_PD_A1CNN0, R8A779A0_PD_A2CN0 },
{ "a1cnn2", R8A779A0_PD_A1CNN2, R8A779A0_PD_A2CN2 },
{ "a1dsp0", R8A779A0_PD_A1DSP0, R8A779A0_PD_A2CN2 },
{ "a1cnn1", R8A779A0_PD_A1CNN1, R8A779A0_PD_A2CN1 },
{ "a1dsp1", R8A779A0_PD_A1DSP1, R8A779A0_PD_A2CN1 },
};
const struct rcar_gen4_sysc_info r8a779a0_sysc_info __initconst = {
.areas = r8a779a0_areas,
.num_areas = ARRAY_SIZE(r8a779a0_areas),
};
@@ -0,0 +1,35 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Renesas R-Car S4-8 System Controller
*
* Copyright (C) 2021 Renesas Electronics Corp.
*/
#include <linux/kernel.h>
#include <dt-bindings/power/r8a779f0-sysc.h>
#include "rcar-gen4-sysc.h"
static struct rcar_gen4_sysc_area r8a779f0_areas[] __initdata = {
{ "always-on", R8A779F0_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
{ "a3e0", R8A779F0_PD_A3E0, R8A779F0_PD_ALWAYS_ON, PD_SCU },
{ "a3e1", R8A779F0_PD_A3E1, R8A779F0_PD_ALWAYS_ON, PD_SCU },
{ "a2e0d0", R8A779F0_PD_A2E0D0, R8A779F0_PD_A3E0, PD_SCU },
{ "a2e0d1", R8A779F0_PD_A2E0D1, R8A779F0_PD_A3E0, PD_SCU },
{ "a2e1d0", R8A779F0_PD_A2E1D0, R8A779F0_PD_A3E1, PD_SCU },
{ "a2e1d1", R8A779F0_PD_A2E1D1, R8A779F0_PD_A3E1, PD_SCU },
{ "a1e0d0c0", R8A779F0_PD_A1E0D0C0, R8A779F0_PD_A2E0D0, PD_CPU_NOCR },
{ "a1e0d0c1", R8A779F0_PD_A1E0D0C1, R8A779F0_PD_A2E0D0, PD_CPU_NOCR },
{ "a1e0d1c0", R8A779F0_PD_A1E0D1C0, R8A779F0_PD_A2E0D1, PD_CPU_NOCR },
{ "a1e0d1c1", R8A779F0_PD_A1E0D1C1, R8A779F0_PD_A2E0D1, PD_CPU_NOCR },
{ "a1e1d0c0", R8A779F0_PD_A1E1D0C0, R8A779F0_PD_A2E1D0, PD_CPU_NOCR },
{ "a1e1d0c1", R8A779F0_PD_A1E1D0C1, R8A779F0_PD_A2E1D0, PD_CPU_NOCR },
{ "a1e1d1c0", R8A779F0_PD_A1E1D1C0, R8A779F0_PD_A2E1D1, PD_CPU_NOCR },
{ "a1e1d1c1", R8A779F0_PD_A1E1D1C1, R8A779F0_PD_A2E1D1, PD_CPU_NOCR },
};
const struct rcar_gen4_sysc_info r8a779f0_sysc_info __initconst = {
.areas = r8a779f0_areas,
.num_areas = ARRAY_SIZE(r8a779f0_areas),
};
@@ -0,0 +1,51 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Renesas R-Car V4H System Controller
*
* Copyright (C) 2022 Renesas Electronics Corp.
*/
#include <linux/kernel.h>
#include <dt-bindings/power/r8a779g0-sysc.h>
#include "rcar-gen4-sysc.h"
static struct rcar_gen4_sysc_area r8a779g0_areas[] __initdata = {
{ "always-on", R8A779G0_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
{ "a3e0", R8A779G0_PD_A3E0, R8A779G0_PD_ALWAYS_ON, PD_SCU },
{ "a2e0d0", R8A779G0_PD_A2E0D0, R8A779G0_PD_A3E0, PD_SCU },
{ "a2e0d1", R8A779G0_PD_A2E0D1, R8A779G0_PD_A3E0, PD_SCU },
{ "a1e0d0c0", R8A779G0_PD_A1E0D0C0, R8A779G0_PD_A2E0D0, PD_CPU_NOCR },
{ "a1e0d0c1", R8A779G0_PD_A1E0D0C1, R8A779G0_PD_A2E0D0, PD_CPU_NOCR },
{ "a1e0d1c0", R8A779G0_PD_A1E0D1C0, R8A779G0_PD_A2E0D1, PD_CPU_NOCR },
{ "a1e0d1c1", R8A779G0_PD_A1E0D1C1, R8A779G0_PD_A2E0D1, PD_CPU_NOCR },
{ "a33dga", R8A779G0_PD_A33DGA, R8A779G0_PD_ALWAYS_ON },
{ "a23dgb", R8A779G0_PD_A23DGB, R8A779G0_PD_A33DGA },
{ "a3vip0", R8A779G0_PD_A3VIP0, R8A779G0_PD_ALWAYS_ON },
{ "a3vip1", R8A779G0_PD_A3VIP1, R8A779G0_PD_ALWAYS_ON },
{ "a3vip2", R8A779G0_PD_A3VIP2, R8A779G0_PD_ALWAYS_ON },
{ "a3dul", R8A779G0_PD_A3DUL, R8A779G0_PD_ALWAYS_ON },
{ "a3isp0", R8A779G0_PD_A3ISP0, R8A779G0_PD_ALWAYS_ON },
{ "a3isp1", R8A779G0_PD_A3ISP1, R8A779G0_PD_ALWAYS_ON },
{ "a3ir", R8A779G0_PD_A3IR, R8A779G0_PD_ALWAYS_ON },
{ "a2cn0", R8A779G0_PD_A2CN0, R8A779G0_PD_A3IR },
{ "a1cnn0", R8A779G0_PD_A1CNN0, R8A779G0_PD_A2CN0 },
{ "a1dsp0", R8A779G0_PD_A1DSP0, R8A779G0_PD_A2CN0 },
{ "a1dsp1", R8A779G0_PD_A1DSP1, R8A779G0_PD_A2CN0 },
{ "a1dsp2", R8A779G0_PD_A1DSP2, R8A779G0_PD_A2CN0 },
{ "a1dsp3", R8A779G0_PD_A1DSP3, R8A779G0_PD_A2CN0 },
{ "a2imp01", R8A779G0_PD_A2IMP01, R8A779G0_PD_A3IR },
{ "a2imp23", R8A779G0_PD_A2IMP23, R8A779G0_PD_A3IR },
{ "a2psc", R8A779G0_PD_A2PSC, R8A779G0_PD_A3IR },
{ "a2dma", R8A779G0_PD_A2DMA, R8A779G0_PD_A3IR },
{ "a2cv0", R8A779G0_PD_A2CV0, R8A779G0_PD_A3IR },
{ "a2cv1", R8A779G0_PD_A2CV1, R8A779G0_PD_A3IR },
{ "a2cv2", R8A779G0_PD_A2CV2, R8A779G0_PD_A3IR },
{ "a2cv3", R8A779G0_PD_A2CV3, R8A779G0_PD_A3IR },
};
const struct rcar_gen4_sysc_info r8a779g0_sysc_info __initconst = {
.areas = r8a779g0_areas,
.num_areas = ARRAY_SIZE(r8a779g0_areas),
};
@@ -0,0 +1,54 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Renesas R-Car V4M System Controller
*
* Copyright (C) 2023 Renesas Electronics Corp
*/
#include <linux/kernel.h>
#include <dt-bindings/power/renesas,r8a779h0-sysc.h>
#include "rcar-gen4-sysc.h"
static struct rcar_gen4_sysc_area r8a779h0_areas[] __initdata = {
{ "always-on", R8A779H0_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
{ "c4", R8A779H0_PD_C4, R8A779H0_PD_ALWAYS_ON },
{ "a2e0d0", R8A779H0_PD_A2E0D0, R8A779H0_PD_C4, PD_SCU },
{ "a1e0d0c0", R8A779H0_PD_A1E0D0C0, R8A779H0_PD_A2E0D0, PD_CPU_NOCR },
{ "a1e0d0c1", R8A779H0_PD_A1E0D0C1, R8A779H0_PD_A2E0D0, PD_CPU_NOCR },
{ "a1e0d0c2", R8A779H0_PD_A1E0D0C2, R8A779H0_PD_A2E0D0, PD_CPU_NOCR },
{ "a1e0d0c3", R8A779H0_PD_A1E0D0C3, R8A779H0_PD_A2E0D0, PD_CPU_NOCR },
{ "a3cr0", R8A779H0_PD_A3CR0, R8A779H0_PD_ALWAYS_ON, PD_CPU_NOCR },
{ "a3cr1", R8A779H0_PD_A3CR1, R8A779H0_PD_ALWAYS_ON, PD_CPU_NOCR },
{ "a3cr2", R8A779H0_PD_A3CR2, R8A779H0_PD_ALWAYS_ON, PD_CPU_NOCR },
{ "a33dga", R8A779H0_PD_A33DGA, R8A779H0_PD_C4 },
{ "a23dgb", R8A779H0_PD_A23DGB, R8A779H0_PD_A33DGA },
{ "a3vip0", R8A779H0_PD_A3VIP0, R8A779H0_PD_C4 },
{ "a3vip2", R8A779H0_PD_A3VIP2, R8A779H0_PD_C4 },
{ "a3dul", R8A779H0_PD_A3DUL, R8A779H0_PD_C4 },
{ "a3isp0", R8A779H0_PD_A3ISP0, R8A779H0_PD_C4 },
{ "a2cn0", R8A779H0_PD_A2CN0, R8A779H0_PD_C4 },
{ "a1cn0", R8A779H0_PD_A1CN0, R8A779H0_PD_A2CN0 },
{ "a1dsp0", R8A779H0_PD_A1DSP0, R8A779H0_PD_A2CN0 },
{ "a1dsp1", R8A779H0_PD_A1DSP1, R8A779H0_PD_A2CN0 },
{ "a2imp01", R8A779H0_PD_A2IMP01, R8A779H0_PD_C4 },
{ "a2psc", R8A779H0_PD_A2PSC, R8A779H0_PD_C4 },
{ "a2dma", R8A779H0_PD_A2DMA, R8A779H0_PD_C4 },
{ "a2cv0", R8A779H0_PD_A2CV0, R8A779H0_PD_C4 },
{ "a2cv1", R8A779H0_PD_A2CV1, R8A779H0_PD_C4 },
{ "a2cv2", R8A779H0_PD_A2CV2, R8A779H0_PD_C4 },
{ "a2cv3", R8A779H0_PD_A2CV3, R8A779H0_PD_C4 },
{ "a3imr0", R8A779H0_PD_A3IMR0, R8A779H0_PD_C4 },
{ "a3imr1", R8A779H0_PD_A3IMR1, R8A779H0_PD_C4 },
{ "a3imr2", R8A779H0_PD_A3IMR2, R8A779H0_PD_C4 },
{ "a3imr3", R8A779H0_PD_A3IMR3, R8A779H0_PD_C4 },
{ "a3vc", R8A779H0_PD_A3VC, R8A779H0_PD_C4 },
{ "a3pci", R8A779H0_PD_A3PCI, R8A779H0_PD_C4 },
{ "a2pciphy", R8A779H0_PD_A2PCIPHY, R8A779H0_PD_A3PCI },
};
const struct rcar_gen4_sysc_info r8a779h0_sysc_info __initconst = {
.areas = r8a779h0_areas,
.num_areas = ARRAY_SIZE(r8a779h0_areas),
};
@@ -0,0 +1,378 @@
// SPDX-License-Identifier: GPL-2.0
/*
* R-Car Gen4 SYSC Power management support
*
* Copyright (C) 2021 Renesas Electronics Corp.
*/
#include <linux/bits.h>
#include <linux/clk/renesas.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/of_address.h>
#include <linux/pm_domain.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/types.h>
#include "rcar-gen4-sysc.h"
/* SYSC Common */
#define SYSCSR 0x000 /* SYSC Status Register */
#define SYSCPONSR(x) (0x800 + ((x) * 0x4)) /* Power-ON Status Register 0 */
#define SYSCPOFFSR(x) (0x808 + ((x) * 0x4)) /* Power-OFF Status Register */
#define SYSCISCR(x) (0x810 + ((x) * 0x4)) /* Interrupt Status/Clear Register */
#define SYSCIER(x) (0x820 + ((x) * 0x4)) /* Interrupt Enable Register */
#define SYSCIMR(x) (0x830 + ((x) * 0x4)) /* Interrupt Mask Register */
/* Power Domain Registers */
#define PDRSR(n) (0x1000 + ((n) * 0x40))
#define PDRONCR(n) (0x1004 + ((n) * 0x40))
#define PDROFFCR(n) (0x1008 + ((n) * 0x40))
#define PDRESR(n) (0x100C + ((n) * 0x40))
/* PWRON/PWROFF */
#define PWRON_PWROFF BIT(0) /* Power-ON/OFF request */
/* PDRESR */
#define PDRESR_ERR BIT(0)
/* PDRSR */
#define PDRSR_OFF BIT(0) /* Power-OFF state */
#define PDRSR_ON BIT(4) /* Power-ON state */
#define PDRSR_OFF_STATE BIT(8) /* Processing Power-OFF sequence */
#define PDRSR_ON_STATE BIT(12) /* Processing Power-ON sequence */
#define SYSCSR_BUSY GENMASK(1, 0) /* All bit sets is not busy */
#define SYSCSR_TIMEOUT 10000
#define SYSCSR_DELAY_US 1
#define PDRESR_RETRIES 10000
#define PDRESR_DELAY_US 1
#define SYSCISCR_TIMEOUT 10000
#define SYSCISCR_DELAY_US 1
#define RCAR_GEN4_PD_ALWAYS_ON 64
#define NUM_DOMAINS_EACH_REG BITS_PER_TYPE(u32)
static void __iomem *rcar_gen4_sysc_base;
static DEFINE_SPINLOCK(rcar_gen4_sysc_lock); /* SMP CPUs + I/O devices */
static int rcar_gen4_sysc_pwr_on_off(u8 pdr, bool on)
{
unsigned int reg_offs;
u32 val;
int ret;
if (on)
reg_offs = PDRONCR(pdr);
else
reg_offs = PDROFFCR(pdr);
/* Wait until SYSC is ready to accept a power request */
ret = readl_poll_timeout_atomic(rcar_gen4_sysc_base + SYSCSR, val,
(val & SYSCSR_BUSY) == SYSCSR_BUSY,
SYSCSR_DELAY_US, SYSCSR_TIMEOUT);
if (ret < 0)
return -EAGAIN;
/* Submit power shutoff or power resume request */
iowrite32(PWRON_PWROFF, rcar_gen4_sysc_base + reg_offs);
return 0;
}
static int clear_irq_flags(unsigned int reg_idx, unsigned int isr_mask)
{
u32 val;
int ret;
iowrite32(isr_mask, rcar_gen4_sysc_base + SYSCISCR(reg_idx));
ret = readl_poll_timeout_atomic(rcar_gen4_sysc_base + SYSCISCR(reg_idx),
val, !(val & isr_mask),
SYSCISCR_DELAY_US, SYSCISCR_TIMEOUT);
if (ret < 0) {
pr_err("\n %s : Can not clear IRQ flags in SYSCISCR", __func__);
return -EIO;
}
return 0;
}
static int rcar_gen4_sysc_power(u8 pdr, bool on)
{
unsigned int isr_mask;
unsigned int reg_idx, bit_idx;
unsigned int status;
unsigned long flags;
int ret = 0;
u32 val;
int k;
spin_lock_irqsave(&rcar_gen4_sysc_lock, flags);
reg_idx = pdr / NUM_DOMAINS_EACH_REG;
bit_idx = pdr % NUM_DOMAINS_EACH_REG;
isr_mask = BIT(bit_idx);
/*
* The interrupt source needs to be enabled, but masked, to prevent the
* CPU from receiving it.
*/
iowrite32(ioread32(rcar_gen4_sysc_base + SYSCIER(reg_idx)) | isr_mask,
rcar_gen4_sysc_base + SYSCIER(reg_idx));
iowrite32(ioread32(rcar_gen4_sysc_base + SYSCIMR(reg_idx)) | isr_mask,
rcar_gen4_sysc_base + SYSCIMR(reg_idx));
ret = clear_irq_flags(reg_idx, isr_mask);
if (ret)
goto out;
/* Submit power shutoff or resume request until it was accepted */
for (k = 0; k < PDRESR_RETRIES; k++) {
ret = rcar_gen4_sysc_pwr_on_off(pdr, on);
if (ret)
goto out;
status = ioread32(rcar_gen4_sysc_base + PDRESR(pdr));
if (!(status & PDRESR_ERR))
break;
udelay(PDRESR_DELAY_US);
}
if (k == PDRESR_RETRIES) {
ret = -EIO;
goto out;
}
/* Wait until the power shutoff or resume request has completed * */
ret = readl_poll_timeout_atomic(rcar_gen4_sysc_base + SYSCISCR(reg_idx),
val, (val & isr_mask),
SYSCISCR_DELAY_US, SYSCISCR_TIMEOUT);
if (ret < 0) {
ret = -EIO;
goto out;
}
/* Clear interrupt flags */
ret = clear_irq_flags(reg_idx, isr_mask);
if (ret)
goto out;
out:
spin_unlock_irqrestore(&rcar_gen4_sysc_lock, flags);
pr_debug("sysc power %s domain %d: %08x -> %d\n", on ? "on" : "off",
pdr, ioread32(rcar_gen4_sysc_base + SYSCISCR(reg_idx)), ret);
return ret;
}
static bool rcar_gen4_sysc_power_is_off(u8 pdr)
{
unsigned int st;
st = ioread32(rcar_gen4_sysc_base + PDRSR(pdr));
if (st & PDRSR_OFF)
return true;
return false;
}
struct rcar_gen4_sysc_pd {
struct generic_pm_domain genpd;
u8 pdr;
unsigned int flags;
char name[];
};
static inline struct rcar_gen4_sysc_pd *to_rcar_gen4_pd(struct generic_pm_domain *d)
{
return container_of(d, struct rcar_gen4_sysc_pd, genpd);
}
static int rcar_gen4_sysc_pd_power_off(struct generic_pm_domain *genpd)
{
struct rcar_gen4_sysc_pd *pd = to_rcar_gen4_pd(genpd);
pr_debug("%s: %s\n", __func__, genpd->name);
return rcar_gen4_sysc_power(pd->pdr, false);
}
static int rcar_gen4_sysc_pd_power_on(struct generic_pm_domain *genpd)
{
struct rcar_gen4_sysc_pd *pd = to_rcar_gen4_pd(genpd);
pr_debug("%s: %s\n", __func__, genpd->name);
return rcar_gen4_sysc_power(pd->pdr, true);
}
static int __init rcar_gen4_sysc_pd_setup(struct rcar_gen4_sysc_pd *pd)
{
struct generic_pm_domain *genpd = &pd->genpd;
const char *name = pd->genpd.name;
int error;
if (pd->flags & PD_CPU) {
/*
* This domain contains a CPU core and therefore it should
* only be turned off if the CPU is not in use.
*/
pr_debug("PM domain %s contains %s\n", name, "CPU");
genpd->flags |= GENPD_FLAG_ALWAYS_ON;
} else if (pd->flags & PD_SCU) {
/*
* This domain contains an SCU and cache-controller, and
* therefore it should only be turned off if the CPU cores are
* not in use.
*/
pr_debug("PM domain %s contains %s\n", name, "SCU");
genpd->flags |= GENPD_FLAG_ALWAYS_ON;
} else if (pd->flags & PD_NO_CR) {
/*
* This domain cannot be turned off.
*/
genpd->flags |= GENPD_FLAG_ALWAYS_ON;
}
if (!(pd->flags & (PD_CPU | PD_SCU))) {
/* Enable Clock Domain for I/O devices */
genpd->flags |= GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP;
genpd->attach_dev = cpg_mssr_attach_dev;
genpd->detach_dev = cpg_mssr_detach_dev;
}
genpd->flags |= GENPD_FLAG_NO_STAY_ON;
genpd->power_off = rcar_gen4_sysc_pd_power_off;
genpd->power_on = rcar_gen4_sysc_pd_power_on;
if (pd->flags & (PD_CPU | PD_NO_CR)) {
/* Skip CPUs (handled by SMP code) and areas without control */
pr_debug("%s: Not touching %s\n", __func__, genpd->name);
goto finalize;
}
if (!rcar_gen4_sysc_power_is_off(pd->pdr)) {
pr_debug("%s: %s is already powered\n", __func__, genpd->name);
goto finalize;
}
rcar_gen4_sysc_power(pd->pdr, true);
finalize:
error = pm_genpd_init(genpd, &simple_qos_governor, false);
if (error)
pr_err("Failed to init PM domain %s: %d\n", name, error);
return error;
}
static const struct of_device_id rcar_gen4_sysc_matches[] __initconst = {
#ifdef CONFIG_SYSC_R8A779A0
{ .compatible = "renesas,r8a779a0-sysc", .data = &r8a779a0_sysc_info },
#endif
#ifdef CONFIG_SYSC_R8A779F0
{ .compatible = "renesas,r8a779f0-sysc", .data = &r8a779f0_sysc_info },
#endif
#ifdef CONFIG_SYSC_R8A779G0
{ .compatible = "renesas,r8a779g0-sysc", .data = &r8a779g0_sysc_info },
#endif
#ifdef CONFIG_SYSC_R8A779H0
{ .compatible = "renesas,r8a779h0-sysc", .data = &r8a779h0_sysc_info },
#endif
{ /* sentinel */ }
};
struct rcar_gen4_pm_domains {
struct genpd_onecell_data onecell_data;
struct generic_pm_domain *domains[RCAR_GEN4_PD_ALWAYS_ON + 1];
};
static struct genpd_onecell_data *rcar_gen4_sysc_onecell_data;
static int __init rcar_gen4_sysc_pd_init(void)
{
const struct rcar_gen4_sysc_info *info;
const struct of_device_id *match;
struct rcar_gen4_pm_domains *domains;
struct device_node *np;
void __iomem *base;
unsigned int i;
int error;
np = of_find_matching_node_and_match(NULL, rcar_gen4_sysc_matches, &match);
if (!np)
return -ENODEV;
info = match->data;
base = of_iomap(np, 0);
if (!base) {
pr_warn("%pOF: Cannot map regs\n", np);
error = -ENOMEM;
goto out_put;
}
rcar_gen4_sysc_base = base;
domains = kzalloc_obj(*domains);
if (!domains) {
error = -ENOMEM;
goto out_put;
}
domains->onecell_data.domains = domains->domains;
domains->onecell_data.num_domains = ARRAY_SIZE(domains->domains);
rcar_gen4_sysc_onecell_data = &domains->onecell_data;
for (i = 0; i < info->num_areas; i++) {
const struct rcar_gen4_sysc_area *area = &info->areas[i];
struct rcar_gen4_sysc_pd *pd;
size_t n;
n = strlen(area->name) + 1;
pd = kzalloc(sizeof(*pd) + n, GFP_KERNEL);
if (!pd) {
error = -ENOMEM;
goto out_put;
}
memcpy(pd->name, area->name, n);
pd->genpd.name = pd->name;
pd->pdr = area->pdr;
pd->flags = area->flags;
error = rcar_gen4_sysc_pd_setup(pd);
if (error)
goto out_put;
domains->domains[area->pdr] = &pd->genpd;
if (area->parent < 0)
continue;
error = pm_genpd_add_subdomain(domains->domains[area->parent],
&pd->genpd);
if (error) {
pr_warn("Failed to add PM subdomain %s to parent %u\n",
area->name, area->parent);
goto out_put;
}
}
error = of_genpd_add_provider_onecell(np, &domains->onecell_data);
out_put:
of_node_put(np);
return error;
}
postcore_initcall(rcar_gen4_sysc_pd_init);
@@ -0,0 +1,45 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* R-Car Gen4 System Controller
*
* Copyright (C) 2021 Renesas Electronics Corp.
*/
#ifndef __SOC_RENESAS_RCAR_GEN4_SYSC_H__
#define __SOC_RENESAS_RCAR_GEN4_SYSC_H__
#include <linux/types.h>
/*
* Power Domain flags
*/
#define PD_CPU BIT(0) /* Area contains main CPU core */
#define PD_SCU BIT(1) /* Area contains SCU and L2 cache */
#define PD_NO_CR BIT(2) /* Area lacks PWR{ON,OFF}CR registers */
#define PD_CPU_NOCR (PD_CPU | PD_NO_CR) /* CPU area lacks CR */
#define PD_ALWAYS_ON PD_NO_CR /* Always-on area */
/*
* Description of a Power Area
*/
struct rcar_gen4_sysc_area {
const char *name;
u8 pdr; /* PDRn */
s8 parent; /* -1 if none */
u8 flags; /* See PD_* */
};
/*
* SoC-specific Power Area Description
*/
struct rcar_gen4_sysc_info {
const struct rcar_gen4_sysc_area *areas;
unsigned int num_areas;
};
extern const struct rcar_gen4_sysc_info r8a779a0_sysc_info;
extern const struct rcar_gen4_sysc_info r8a779f0_sysc_info;
extern const struct rcar_gen4_sysc_info r8a779g0_sysc_info;
extern const struct rcar_gen4_sysc_info r8a779h0_sysc_info;
#endif /* __SOC_RENESAS_RCAR_GEN4_SYSC_H__ */
@@ -0,0 +1,491 @@
// SPDX-License-Identifier: GPL-2.0
/*
* R-Car SYSC Power management support
*
* Copyright (C) 2014 Magnus Damm
* Copyright (C) 2015-2017 Glider bvba
*/
#include <linux/clk/renesas.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/mm.h>
#include <linux/of_address.h>
#include <linux/pm_domain.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/soc/renesas/rcar-sysc.h>
#include "rcar-sysc.h"
/* SYSC Common */
#define SYSCSR 0x00 /* SYSC Status Register */
#define SYSCISR 0x04 /* Interrupt Status Register */
#define SYSCISCR 0x08 /* Interrupt Status Clear Register */
#define SYSCIER 0x0c /* Interrupt Enable Register */
#define SYSCIMR 0x10 /* Interrupt Mask Register */
/* SYSC Status Register */
#define SYSCSR_PONENB 1 /* Ready for power resume requests */
#define SYSCSR_POFFENB 0 /* Ready for power shutoff requests */
/*
* Power Control Register Offsets inside the register block for each domain
* Note: The "CR" registers for ARM cores exist on H1 only
* Use WFI to power off, CPG/APMU to resume ARM cores on R-Car Gen2
* Use PSCI on R-Car Gen3
*/
#define PWRSR_OFFS 0x00 /* Power Status Register */
#define PWROFFCR_OFFS 0x04 /* Power Shutoff Control Register */
#define PWROFFSR_OFFS 0x08 /* Power Shutoff Status Register */
#define PWRONCR_OFFS 0x0c /* Power Resume Control Register */
#define PWRONSR_OFFS 0x10 /* Power Resume Status Register */
#define PWRER_OFFS 0x14 /* Power Shutoff/Resume Error */
#define SYSCSR_TIMEOUT 1000
#define SYSCSR_DELAY_US 1
#define PWRER_RETRIES 1000
#define PWRER_DELAY_US 1
#define SYSCISR_TIMEOUT 1000
#define SYSCISR_DELAY_US 1
#define RCAR_PD_ALWAYS_ON 32 /* Always-on power area */
struct rcar_sysc_pd {
struct generic_pm_domain genpd;
u16 chan_offs;
u8 chan_bit;
u8 isr_bit;
unsigned int flags;
char name[];
};
static void __iomem *rcar_sysc_base;
static DEFINE_SPINLOCK(rcar_sysc_lock); /* SMP CPUs + I/O devices */
static u32 rcar_sysc_extmask_offs, rcar_sysc_extmask_val;
static int rcar_sysc_pwr_on_off(const struct rcar_sysc_pd *pd, bool on)
{
unsigned int sr_bit, reg_offs;
u32 val;
int ret;
if (on) {
sr_bit = SYSCSR_PONENB;
reg_offs = PWRONCR_OFFS;
} else {
sr_bit = SYSCSR_POFFENB;
reg_offs = PWROFFCR_OFFS;
}
/* Wait until SYSC is ready to accept a power request */
ret = readl_poll_timeout_atomic(rcar_sysc_base + SYSCSR, val,
val & BIT(sr_bit), SYSCSR_DELAY_US,
SYSCSR_TIMEOUT);
if (ret)
return -EAGAIN;
/* Power-off delay quirk */
if (!on && (pd->flags & PD_OFF_DELAY))
udelay(1);
/* Submit power shutoff or power resume request */
iowrite32(BIT(pd->chan_bit), rcar_sysc_base + pd->chan_offs + reg_offs);
return 0;
}
static int rcar_sysc_power(const struct rcar_sysc_pd *pd, bool on)
{
unsigned int isr_mask = BIT(pd->isr_bit);
unsigned int chan_mask = BIT(pd->chan_bit);
unsigned int status, k;
unsigned long flags;
int ret;
spin_lock_irqsave(&rcar_sysc_lock, flags);
/*
* Mask external power requests for CPU or 3DG domains
*/
if (rcar_sysc_extmask_val) {
iowrite32(rcar_sysc_extmask_val,
rcar_sysc_base + rcar_sysc_extmask_offs);
}
/*
* The interrupt source needs to be enabled, but masked, to prevent the
* CPU from receiving it.
*/
iowrite32(ioread32(rcar_sysc_base + SYSCIMR) | isr_mask,
rcar_sysc_base + SYSCIMR);
iowrite32(ioread32(rcar_sysc_base + SYSCIER) | isr_mask,
rcar_sysc_base + SYSCIER);
iowrite32(isr_mask, rcar_sysc_base + SYSCISCR);
/* Submit power shutoff or resume request until it was accepted */
for (k = 0; k < PWRER_RETRIES; k++) {
ret = rcar_sysc_pwr_on_off(pd, on);
if (ret)
goto out;
status = ioread32(rcar_sysc_base + pd->chan_offs + PWRER_OFFS);
if (!(status & chan_mask))
break;
udelay(PWRER_DELAY_US);
}
if (k == PWRER_RETRIES) {
ret = -EIO;
goto out;
}
/* Wait until the power shutoff or resume request has completed * */
ret = readl_poll_timeout_atomic(rcar_sysc_base + SYSCISR, status,
status & isr_mask, SYSCISR_DELAY_US,
SYSCISR_TIMEOUT);
if (ret)
ret = -EIO;
iowrite32(isr_mask, rcar_sysc_base + SYSCISCR);
out:
if (rcar_sysc_extmask_val)
iowrite32(0, rcar_sysc_base + rcar_sysc_extmask_offs);
spin_unlock_irqrestore(&rcar_sysc_lock, flags);
pr_debug("sysc power %s domain %d: %08x -> %d\n", on ? "on" : "off",
pd->isr_bit, ioread32(rcar_sysc_base + SYSCISR), ret);
return ret;
}
static bool rcar_sysc_power_is_off(const struct rcar_sysc_pd *pd)
{
unsigned int st;
st = ioread32(rcar_sysc_base + pd->chan_offs + PWRSR_OFFS);
if (st & BIT(pd->chan_bit))
return true;
return false;
}
static inline struct rcar_sysc_pd *to_rcar_pd(struct generic_pm_domain *d)
{
return container_of(d, struct rcar_sysc_pd, genpd);
}
static int rcar_sysc_pd_power_off(struct generic_pm_domain *genpd)
{
struct rcar_sysc_pd *pd = to_rcar_pd(genpd);
pr_debug("%s: %s\n", __func__, genpd->name);
return rcar_sysc_power(pd, false);
}
static int rcar_sysc_pd_power_on(struct generic_pm_domain *genpd)
{
struct rcar_sysc_pd *pd = to_rcar_pd(genpd);
pr_debug("%s: %s\n", __func__, genpd->name);
return rcar_sysc_power(pd, true);
}
static bool has_cpg_mstp;
static int __init rcar_sysc_pd_setup(struct rcar_sysc_pd *pd)
{
struct generic_pm_domain *genpd = &pd->genpd;
const char *name = pd->genpd.name;
int error;
if (pd->flags & PD_CPU) {
/*
* This domain contains a CPU core and therefore it should
* only be turned off if the CPU is not in use.
*/
pr_debug("PM domain %s contains %s\n", name, "CPU");
genpd->flags |= GENPD_FLAG_ALWAYS_ON;
} else if (pd->flags & PD_SCU) {
/*
* This domain contains an SCU and cache-controller, and
* therefore it should only be turned off if the CPU cores are
* not in use.
*/
pr_debug("PM domain %s contains %s\n", name, "SCU");
genpd->flags |= GENPD_FLAG_ALWAYS_ON;
} else if (pd->flags & PD_NO_CR) {
/*
* This domain cannot be turned off.
*/
genpd->flags |= GENPD_FLAG_ALWAYS_ON;
}
if (!(pd->flags & (PD_CPU | PD_SCU))) {
/* Enable Clock Domain for I/O devices */
genpd->flags |= GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP;
if (has_cpg_mstp) {
genpd->attach_dev = cpg_mstp_attach_dev;
genpd->detach_dev = cpg_mstp_detach_dev;
} else {
genpd->attach_dev = cpg_mssr_attach_dev;
genpd->detach_dev = cpg_mssr_detach_dev;
}
}
genpd->flags |= GENPD_FLAG_NO_STAY_ON;
genpd->power_off = rcar_sysc_pd_power_off;
genpd->power_on = rcar_sysc_pd_power_on;
if (pd->flags & (PD_CPU | PD_NO_CR)) {
/* Skip CPUs (handled by SMP code) and areas without control */
pr_debug("%s: Not touching %s\n", __func__, genpd->name);
goto finalize;
}
if (!rcar_sysc_power_is_off(pd)) {
pr_debug("%s: %s is already powered\n", __func__, genpd->name);
goto finalize;
}
rcar_sysc_power(pd, true);
finalize:
error = pm_genpd_init(genpd, &simple_qos_governor, false);
if (error)
pr_err("Failed to init PM domain %s: %d\n", name, error);
return error;
}
static const struct of_device_id rcar_sysc_matches[] __initconst = {
#ifdef CONFIG_SYSC_R8A7742
{ .compatible = "renesas,r8a7742-sysc", .data = &r8a7742_sysc_info },
#endif
#ifdef CONFIG_SYSC_R8A7743
{ .compatible = "renesas,r8a7743-sysc", .data = &r8a7743_sysc_info },
/* RZ/G1N is identical to RZ/G2M w.r.t. power domains. */
{ .compatible = "renesas,r8a7744-sysc", .data = &r8a7743_sysc_info },
#endif
#ifdef CONFIG_SYSC_R8A7745
{ .compatible = "renesas,r8a7745-sysc", .data = &r8a7745_sysc_info },
#endif
#ifdef CONFIG_SYSC_R8A77470
{ .compatible = "renesas,r8a77470-sysc", .data = &r8a77470_sysc_info },
#endif
#ifdef CONFIG_SYSC_R8A774A1
{ .compatible = "renesas,r8a774a1-sysc", .data = &r8a774a1_sysc_info },
#endif
#ifdef CONFIG_SYSC_R8A774B1
{ .compatible = "renesas,r8a774b1-sysc", .data = &r8a774b1_sysc_info },
#endif
#ifdef CONFIG_SYSC_R8A774C0
{ .compatible = "renesas,r8a774c0-sysc", .data = &r8a774c0_sysc_info },
#endif
#ifdef CONFIG_SYSC_R8A774E1
{ .compatible = "renesas,r8a774e1-sysc", .data = &r8a774e1_sysc_info },
#endif
#ifdef CONFIG_SYSC_R8A7779
{ .compatible = "renesas,r8a7779-sysc", .data = &r8a7779_sysc_info },
#endif
#ifdef CONFIG_SYSC_R8A7790
{ .compatible = "renesas,r8a7790-sysc", .data = &r8a7790_sysc_info },
#endif
#ifdef CONFIG_SYSC_R8A7791
{ .compatible = "renesas,r8a7791-sysc", .data = &r8a7791_sysc_info },
/* R-Car M2-N is identical to R-Car M2-W w.r.t. power domains. */
{ .compatible = "renesas,r8a7793-sysc", .data = &r8a7791_sysc_info },
#endif
#ifdef CONFIG_SYSC_R8A7792
{ .compatible = "renesas,r8a7792-sysc", .data = &r8a7792_sysc_info },
#endif
#ifdef CONFIG_SYSC_R8A7794
{ .compatible = "renesas,r8a7794-sysc", .data = &r8a7794_sysc_info },
#endif
#ifdef CONFIG_SYSC_R8A7795
{ .compatible = "renesas,r8a7795-sysc", .data = &r8a7795_sysc_info },
#endif
#ifdef CONFIG_SYSC_R8A77960
{ .compatible = "renesas,r8a7796-sysc", .data = &r8a77960_sysc_info },
#endif
#ifdef CONFIG_SYSC_R8A77961
{ .compatible = "renesas,r8a77961-sysc", .data = &r8a77961_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
#ifdef CONFIG_SYSC_R8A77980
{ .compatible = "renesas,r8a77980-sysc", .data = &r8a77980_sysc_info },
#endif
#ifdef CONFIG_SYSC_R8A77990
{ .compatible = "renesas,r8a77990-sysc", .data = &r8a77990_sysc_info },
#endif
#ifdef CONFIG_SYSC_R8A77995
{ .compatible = "renesas,r8a77995-sysc", .data = &r8a77995_sysc_info },
#endif
{ /* sentinel */ }
};
struct rcar_pm_domains {
struct genpd_onecell_data onecell_data;
struct generic_pm_domain *domains[RCAR_PD_ALWAYS_ON + 1];
};
static struct genpd_onecell_data *rcar_sysc_onecell_data;
static struct device_node *rcar_sysc_onecell_np __initdata = NULL;
static int __init rcar_sysc_pd_init(void)
{
const struct rcar_sysc_info *info;
const struct of_device_id *match;
struct rcar_pm_domains *domains;
struct device_node *np;
void __iomem *base;
unsigned int i;
int error;
np = of_find_matching_node_and_match(NULL, rcar_sysc_matches, &match);
if (!np)
return -ENODEV;
info = match->data;
if (info->init) {
error = info->init();
if (error)
goto out_put;
}
has_cpg_mstp = of_find_compatible_node(NULL, NULL,
"renesas,cpg-mstp-clocks");
base = of_iomap(np, 0);
if (!base) {
pr_warn("%pOF: Cannot map regs\n", np);
error = -ENOMEM;
goto out_put;
}
rcar_sysc_base = base;
/* Optional External Request Mask Register */
rcar_sysc_extmask_offs = info->extmask_offs;
rcar_sysc_extmask_val = info->extmask_val;
domains = kzalloc_obj(*domains);
if (!domains) {
error = -ENOMEM;
goto out_put;
}
domains->onecell_data.domains = domains->domains;
domains->onecell_data.num_domains = ARRAY_SIZE(domains->domains);
rcar_sysc_onecell_data = &domains->onecell_data;
for (i = 0; i < info->num_areas; i++) {
const struct rcar_sysc_area *area = &info->areas[i];
struct rcar_sysc_pd *pd;
size_t n;
n = strlen(area->name) + 1;
pd = kzalloc(sizeof(*pd) + n, GFP_KERNEL);
if (!pd) {
error = -ENOMEM;
goto out_put;
}
memcpy(pd->name, area->name, n);
pd->genpd.name = pd->name;
pd->chan_offs = area->chan_offs;
pd->chan_bit = area->chan_bit;
pd->isr_bit = area->isr_bit;
pd->flags = area->flags;
error = rcar_sysc_pd_setup(pd);
if (error)
goto out_put;
domains->domains[area->isr_bit] = &pd->genpd;
if (area->parent < 0)
continue;
error = pm_genpd_add_subdomain(domains->domains[area->parent],
&pd->genpd);
if (error) {
pr_warn("Failed to add PM subdomain %s to parent %u\n",
area->name, area->parent);
goto out_put;
}
}
rcar_sysc_onecell_np = np;
return 0;
out_put:
of_node_put(np);
return error;
}
early_initcall(rcar_sysc_pd_init);
static int __init rcar_sysc_pd_init_provider(void)
{
int error;
if (!rcar_sysc_onecell_np)
return -ENODEV;
error = of_genpd_add_provider_onecell(rcar_sysc_onecell_np,
rcar_sysc_onecell_data);
of_node_put(rcar_sysc_onecell_np);
return error;
}
postcore_initcall(rcar_sysc_pd_init_provider);
#ifdef CONFIG_ARCH_R8A7779
static int rcar_sysc_power_cpu(unsigned int idx, bool on)
{
struct generic_pm_domain *genpd;
struct rcar_sysc_pd *pd;
unsigned int i;
if (!rcar_sysc_onecell_data)
return -ENODEV;
for (i = 0; i < rcar_sysc_onecell_data->num_domains; i++) {
genpd = rcar_sysc_onecell_data->domains[i];
if (!genpd)
continue;
pd = to_rcar_pd(genpd);
if (!(pd->flags & PD_CPU) || pd->chan_bit != idx)
continue;
return rcar_sysc_power(pd, on);
}
return -ENOENT;
}
int rcar_sysc_power_down_cpu(unsigned int cpu)
{
return rcar_sysc_power_cpu(cpu, false);
}
int rcar_sysc_power_up_cpu(unsigned int cpu)
{
return rcar_sysc_power_cpu(cpu, true);
}
#endif /* CONFIG_ARCH_R8A7779 */
@@ -0,0 +1,75 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Renesas R-Car System Controller
*
* Copyright (C) 2016 Glider bvba
*/
#ifndef __SOC_RENESAS_RCAR_SYSC_H__
#define __SOC_RENESAS_RCAR_SYSC_H__
#include <linux/types.h>
/*
* Power Domain flags
*/
#define PD_CPU BIT(0) /* Area contains main CPU core */
#define PD_SCU BIT(1) /* Area contains SCU and L2 cache */
#define PD_NO_CR BIT(2) /* Area lacks PWR{ON,OFF}CR registers */
#define PD_OFF_DELAY BIT(3) /* Area is subject to power-off delay quirk */
#define PD_CPU_CR PD_CPU /* CPU area has CR (R-Car H1) */
#define PD_CPU_NOCR PD_CPU | PD_NO_CR /* CPU area lacks CR (R-Car Gen2/3) */
#define PD_ALWAYS_ON PD_NO_CR /* Always-on area */
/*
* Description of a Power Area
*/
struct rcar_sysc_area {
const char *name;
u16 chan_offs; /* Offset of PWRSR register for this area */
u8 chan_bit; /* Bit in PWR* (except for PWRUP in PWRSR) */
u8 isr_bit; /* Bit in SYSCI*R */
s8 parent; /* -1 if none */
u8 flags; /* See PD_* */
};
/*
* SoC-specific Power Area Description
*/
struct rcar_sysc_info {
int (*init)(void); /* Optional */
const struct rcar_sysc_area *areas;
unsigned int num_areas;
/* Optional External Request Mask Register */
u32 extmask_offs; /* SYSCEXTMASK register offset */
u32 extmask_val; /* SYSCEXTMASK register mask value */
};
extern const struct rcar_sysc_info r8a7742_sysc_info;
extern const struct rcar_sysc_info r8a7743_sysc_info;
extern const struct rcar_sysc_info r8a7745_sysc_info;
extern const struct rcar_sysc_info r8a77470_sysc_info;
extern const struct rcar_sysc_info r8a774a1_sysc_info;
extern const struct rcar_sysc_info r8a774b1_sysc_info;
extern const struct rcar_sysc_info r8a774c0_sysc_info;
extern const struct rcar_sysc_info r8a774e1_sysc_info;
extern const struct rcar_sysc_info r8a7779_sysc_info;
extern const struct rcar_sysc_info r8a7790_sysc_info;
extern const struct rcar_sysc_info r8a7791_sysc_info;
extern const struct rcar_sysc_info r8a7792_sysc_info;
extern const struct rcar_sysc_info r8a7794_sysc_info;
extern struct rcar_sysc_info r8a7795_sysc_info;
extern const struct rcar_sysc_info r8a77960_sysc_info;
extern const struct rcar_sysc_info r8a77961_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 r8a77990_sysc_info;
extern const struct rcar_sysc_info r8a77995_sysc_info;
#endif /* __SOC_RENESAS_RCAR_SYSC_H__ */
@@ -0,0 +1,339 @@
// SPDX-License-Identifier: GPL-2.0
/*
* rmobile power management support
*
* Copyright (C) 2012 Renesas Solutions Corp.
* Copyright (C) 2012 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
* Copyright (C) 2014 Glider bvba
*
* based on pm-sh7372.c
* Copyright (C) 2011 Magnus Damm
*/
#include <linux/clk/renesas.h>
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/pm.h>
#include <linux/pm_clock.h>
#include <linux/pm_domain.h>
#include <linux/slab.h>
/* SYSC */
#define SPDCR 0x08 /* SYS Power Down Control Register */
#define SWUCR 0x14 /* SYS Wakeup Control Register */
#define PSTR 0x80 /* Power Status Register */
#define PSTR_RETRIES 100
#define PSTR_DELAY_US 10
struct rmobile_pm_domain {
struct generic_pm_domain genpd;
struct dev_power_governor *gov;
int (*suspend)(void);
void __iomem *base;
unsigned int bit_shift;
};
static inline
struct rmobile_pm_domain *to_rmobile_pd(struct generic_pm_domain *d)
{
return container_of(d, struct rmobile_pm_domain, genpd);
}
static int rmobile_pd_power_down(struct generic_pm_domain *genpd)
{
struct rmobile_pm_domain *rmobile_pd = to_rmobile_pd(genpd);
unsigned int mask = BIT(rmobile_pd->bit_shift);
u32 val;
if (rmobile_pd->suspend) {
int ret = rmobile_pd->suspend();
if (ret)
return ret;
}
if (readl(rmobile_pd->base + PSTR) & mask) {
writel(mask, rmobile_pd->base + SPDCR);
readl_poll_timeout_atomic(rmobile_pd->base + SPDCR, val,
!(val & mask), 0, PSTR_RETRIES);
}
pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n", genpd->name, mask,
readl(rmobile_pd->base + PSTR));
return 0;
}
static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd)
{
unsigned int val, mask = BIT(rmobile_pd->bit_shift);
int ret = 0;
if (readl(rmobile_pd->base + PSTR) & mask)
return ret;
writel(mask, rmobile_pd->base + SWUCR);
ret = readl_poll_timeout_atomic(rmobile_pd->base + SWUCR, val,
(val & mask), PSTR_DELAY_US,
PSTR_RETRIES * PSTR_DELAY_US);
pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n",
rmobile_pd->genpd.name, mask,
readl(rmobile_pd->base + PSTR));
return ret;
}
static int rmobile_pd_power_up(struct generic_pm_domain *genpd)
{
return __rmobile_pd_power_up(to_rmobile_pd(genpd));
}
static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd)
{
struct generic_pm_domain *genpd = &rmobile_pd->genpd;
struct dev_power_governor *gov = rmobile_pd->gov;
genpd->flags |= GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP |
GENPD_FLAG_NO_STAY_ON;
genpd->attach_dev = cpg_mstp_attach_dev;
genpd->detach_dev = cpg_mstp_detach_dev;
if (!(genpd->flags & GENPD_FLAG_ALWAYS_ON)) {
genpd->power_off = rmobile_pd_power_down;
genpd->power_on = rmobile_pd_power_up;
__rmobile_pd_power_up(rmobile_pd);
}
pm_genpd_init(genpd, gov ? : &simple_qos_governor, false);
}
static int rmobile_pd_suspend_console(void)
{
/*
* Serial consoles make use of SCIF hardware located in this domain,
* hence keep the power domain on if "no_console_suspend" is set.
*/
return console_suspend_enabled ? 0 : -EBUSY;
}
enum pd_types {
PD_NORMAL,
PD_CPU,
PD_CONSOLE,
PD_DEBUG,
PD_MEMCTL,
};
#define MAX_NUM_SPECIAL_PDS 16
static struct special_pd {
struct device_node *pd;
enum pd_types type;
} special_pds[MAX_NUM_SPECIAL_PDS] __initdata;
static unsigned int num_special_pds __initdata;
static const struct of_device_id special_ids[] __initconst = {
{ .compatible = "arm,coresight-etm3x", .data = (void *)PD_DEBUG },
{ .compatible = "renesas,dbsc-r8a73a4", .data = (void *)PD_MEMCTL, },
{ .compatible = "renesas,dbsc3-r8a7740", .data = (void *)PD_MEMCTL, },
{ .compatible = "renesas,sbsc-sh73a0", .data = (void *)PD_MEMCTL, },
{ /* sentinel */ },
};
static void __init add_special_pd(struct device_node *np, enum pd_types type)
{
unsigned int i;
struct device_node *pd;
pd = of_parse_phandle(np, "power-domains", 0);
if (!pd)
return;
for (i = 0; i < num_special_pds; i++)
if (pd == special_pds[i].pd && type == special_pds[i].type) {
of_node_put(pd);
return;
}
if (num_special_pds == ARRAY_SIZE(special_pds)) {
pr_warn("Too many special PM domains\n");
of_node_put(pd);
return;
}
pr_debug("Special PM domain %pOFn type %d for %pOF\n", pd, type, np);
special_pds[num_special_pds].pd = pd;
special_pds[num_special_pds].type = type;
num_special_pds++;
}
static void __init get_special_pds(void)
{
struct device_node *np;
const struct of_device_id *id;
/* PM domains containing CPUs */
for_each_of_cpu_node(np)
add_special_pd(np, PD_CPU);
/* PM domain containing console */
if (of_stdout)
add_special_pd(of_stdout, PD_CONSOLE);
/* PM domains containing other special devices */
for_each_matching_node_and_match(np, special_ids, &id)
add_special_pd(np, (uintptr_t)id->data);
}
static void __init put_special_pds(void)
{
unsigned int i;
for (i = 0; i < num_special_pds; i++)
of_node_put(special_pds[i].pd);
}
static enum pd_types __init pd_type(const struct device_node *pd)
{
unsigned int i;
for (i = 0; i < num_special_pds; i++)
if (pd == special_pds[i].pd)
return special_pds[i].type;
return PD_NORMAL;
}
static void __init rmobile_setup_pm_domain(struct device_node *np,
struct rmobile_pm_domain *pd)
{
const char *name = pd->genpd.name;
switch (pd_type(np)) {
case PD_CPU:
/*
* This domain contains the CPU core and therefore it should
* only be turned off if the CPU is not in use.
*/
pr_debug("PM domain %s contains CPU\n", name);
pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
break;
case PD_CONSOLE:
pr_debug("PM domain %s contains serial console\n", name);
pd->gov = &pm_domain_always_on_gov;
pd->suspend = rmobile_pd_suspend_console;
break;
case PD_DEBUG:
/*
* This domain contains the Coresight-ETM hardware block and
* therefore it should only be turned off if the debug module
* is not in use.
*/
pr_debug("PM domain %s contains Coresight-ETM\n", name);
pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
break;
case PD_MEMCTL:
/*
* This domain contains a memory-controller and therefore it
* should only be turned off if memory is not in use.
*/
pr_debug("PM domain %s contains MEMCTL\n", name);
pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
break;
case PD_NORMAL:
if (pd->bit_shift == ~0) {
/* Top-level always-on domain */
pr_debug("PM domain %s is always-on domain\n", name);
pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
}
break;
}
rmobile_init_pm_domain(pd);
}
static int __init rmobile_add_pm_domains(void __iomem *base,
struct device_node *parent,
struct generic_pm_domain *genpd_parent)
{
for_each_child_of_node_scoped(parent, np) {
struct rmobile_pm_domain *pd;
u32 idx = ~0;
if (of_property_read_u32(np, "reg", &idx)) {
/* always-on domain */
}
pd = kzalloc_obj(*pd);
if (!pd)
return -ENOMEM;
pd->genpd.name = np->name;
pd->base = base;
pd->bit_shift = idx;
rmobile_setup_pm_domain(np, pd);
if (genpd_parent)
pm_genpd_add_subdomain(genpd_parent, &pd->genpd);
of_genpd_add_provider_simple(np, &pd->genpd);
rmobile_add_pm_domains(base, np, &pd->genpd);
}
return 0;
}
static int __init rmobile_init_pm_domains(void)
{
struct device_node *np, *pmd;
bool scanned = false;
void __iomem *base;
int ret = 0;
for_each_compatible_node(np, NULL, "renesas,sysc-rmobile") {
base = of_iomap(np, 0);
if (!base) {
pr_warn("%pOF cannot map reg 0\n", np);
continue;
}
pmd = of_get_child_by_name(np, "pm-domains");
if (!pmd) {
iounmap(base);
pr_warn("%pOF lacks pm-domains node\n", np);
continue;
}
if (!scanned) {
/* Find PM domains containing special blocks */
get_special_pds();
scanned = true;
}
ret = rmobile_add_pm_domains(base, pmd, NULL);
of_node_put(pmd);
if (ret) {
of_node_put(np);
break;
}
fwnode_dev_initialized(of_fwnode_handle(np), true);
}
put_special_pds();
return ret;
}
postcore_initcall(rmobile_init_pm_domains);