Merge tag 'samsung-drivers-6.19' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux into soc/drivers

Samsung SoC drivers for v6.19

1. ChipID driver: Add support for identifying Exynos8890 and Exynos9610.

2. PMU driver: Allow specifying list of valid registers for the custom
   regmap used on Google GS101 SoC.  The PMU (Power Management Unit) on
   that SoC uses more complex access to registers than simple MMIO and
   invalid registers trigger aborts halting the system.

3. Few minor cleanups.

4. Several new bindings for compatible devices.

* tag 'samsung-drivers-6.19' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux:
  dt-bindings: soc: samsung: exynos-pmu: allow mipi-phy subnode for Exynos7870 PMU
  soc: samsung: exynos-chipid: use a local dev variable
  dt-bindings: soc: samsung: exynos-sysreg: add gs101 hsi0 and misc compatibles
  dt-bindings: soc: samsung: exynos-sysreg: add power-domains
  soc: samsung: gs101-pmu: implement access tables for read and write
  soc: samsung: exynos-pmu: move some gs101 related code into new file
  soc: samsung: exynos-pmu: allow specifying read & write access tables for secure regmap
  dt-bindings: samsung: exynos-sysreg: add exynos7870 sysregs
  soc: samsung: exynos-chipid: add exynos8890 SoC support
  dt-bindings: hwinfo: samsung,exynos-chipid: add exynos8890-chipid compatible
  dt-bindings: soc: samsung: exynos-pmu: add exynos8890 compatible
  soc: samsung: exynos-pmu: Annotate online/offline functions with __must_hold
  soc: samsung: exynos-chipid: Add exynos9610 SoC support
  dt-bindings: hwinfo: samsung,exynos-chipid: add exynos9610 compatible
  dt-bindings: soc: samsung: exynos-sysreg: Add Exynos990 PERIC0/1 compatibles

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
Arnd Bergmann
2025-11-25 10:21:51 +01:00
10 changed files with 863 additions and 150 deletions

View File

@@ -20,12 +20,14 @@ properties:
- samsung,exynos5433-chipid
- samsung,exynos7-chipid
- samsung,exynos7870-chipid
- samsung,exynos8890-chipid
- const: samsung,exynos4210-chipid
- items:
- enum:
- samsung,exynos2200-chipid
- samsung,exynos7885-chipid
- samsung,exynos8895-chipid
- samsung,exynos9610-chipid
- samsung,exynos9810-chipid
- samsung,exynos990-chipid
- samsung,exynosautov9-chipid

View File

@@ -55,6 +55,7 @@ properties:
- samsung,exynos2200-pmu
- samsung,exynos7870-pmu
- samsung,exynos7885-pmu
- samsung,exynos8890-pmu
- samsung,exynos8895-pmu
- samsung,exynos9810-pmu
- samsung,exynos990-pmu
@@ -172,6 +173,7 @@ allOf:
- samsung,exynos5250-pmu
- samsung,exynos5420-pmu
- samsung,exynos5433-pmu
- samsung,exynos7870-pmu
then:
properties:
mipi-phy: true

View File

@@ -15,7 +15,9 @@ properties:
- items:
- enum:
- google,gs101-apm-sysreg
- google,gs101-hsi0-sysreg
- google,gs101-hsi2-sysreg
- google,gs101-misc-sysreg
- google,gs101-peric0-sysreg
- google,gs101-peric1-sysreg
- samsung,exynos2200-cmgp-sysreg
@@ -26,10 +28,14 @@ properties:
- samsung,exynos3-sysreg
- samsung,exynos4-sysreg
- samsung,exynos5-sysreg
- samsung,exynos7870-cam0-sysreg
- samsung,exynos7870-disp-sysreg
- samsung,exynos8895-fsys0-sysreg
- samsung,exynos8895-fsys1-sysreg
- samsung,exynos8895-peric0-sysreg
- samsung,exynos8895-peric1-sysreg
- samsung,exynos990-peric0-sysreg
- samsung,exynos990-peric1-sysreg
- samsung,exynosautov920-hsi2-sysreg
- samsung,exynosautov920-peric0-sysreg
- samsung,exynosautov920-peric1-sysreg
@@ -73,6 +79,9 @@ properties:
clocks:
maxItems: 1
power-domains:
maxItems: 1
required:
- compatible
- reg
@@ -83,7 +92,9 @@ allOf:
compatible:
contains:
enum:
- google,gs101-hsi0-sysreg
- google,gs101-hsi2-sysreg
- google,gs101-misc-sysreg
- google,gs101-peric0-sysreg
- google,gs101-peric1-sysreg
- samsung,exynos850-cmgp-sysreg
@@ -93,6 +104,8 @@ allOf:
- samsung,exynos8895-fsys1-sysreg
- samsung,exynos8895-peric0-sysreg
- samsung,exynos8895-peric1-sysreg
- samsung,exynos990-peric0-sysreg
- samsung,exynos990-peric1-sysreg
then:
required:
- clocks
@@ -100,6 +113,16 @@ allOf:
properties:
clocks: false
- if:
properties:
compatible:
not:
contains:
pattern: "^google,gs101-[^-]+-sysreg$"
then:
properties:
power-domains: false
additionalProperties: false
examples:

View File

@@ -10600,6 +10600,7 @@ F: Documentation/devicetree/bindings/clock/google,gs101-clock.yaml
F: Documentation/devicetree/bindings/soc/google/google,gs101-pmu-intr-gen.yaml
F: arch/arm64/boot/dts/exynos/google/
F: drivers/clk/samsung/clk-gs101.c
F: drivers/soc/samsung/gs101-pmu.c
F: drivers/phy/samsung/phy-gs101-ufs.c
F: include/dt-bindings/clock/google,gs101.h
K: [gG]oogle.?[tT]ensor

View File

@@ -6,7 +6,8 @@ exynos_chipid-y += exynos-chipid.o exynos-asv.o
obj-$(CONFIG_EXYNOS_USI) += exynos-usi.o
obj-$(CONFIG_EXYNOS_PMU) += exynos-pmu.o
obj-$(CONFIG_EXYNOS_PMU) += exynos_pmu.o
exynos_pmu-y += exynos-pmu.o gs101-pmu.o
obj-$(CONFIG_EXYNOS_PMU_ARM_DRIVERS) += exynos3250-pmu.o exynos4-pmu.o \
exynos5250-pmu.o exynos5420-pmu.o

View File

@@ -57,11 +57,13 @@ static const struct exynos_soc_id {
{ "EXYNOS5800", 0xE5422000 },
{ "EXYNOS7420", 0xE7420000 },
{ "EXYNOS7870", 0xE7870000 },
{ "EXYNOS8890", 0xE8890000 },
/* Compatible with: samsung,exynos850-chipid */
{ "EXYNOS2200", 0xE9925000 },
{ "EXYNOS7885", 0xE7885000 },
{ "EXYNOS850", 0xE3830000 },
{ "EXYNOS8895", 0xE8895000 },
{ "EXYNOS9610", 0xE9610000 },
{ "EXYNOS9810", 0xE9810000 },
{ "EXYNOS990", 0xE9830000 },
{ "EXYNOSAUTOV9", 0xAAA80000 },
@@ -107,16 +109,17 @@ static int exynos_chipid_probe(struct platform_device *pdev)
const struct exynos_chipid_variant *drv_data;
struct exynos_chipid_info soc_info;
struct soc_device_attribute *soc_dev_attr;
struct device *dev = &pdev->dev;
struct soc_device *soc_dev;
struct device_node *root;
struct regmap *regmap;
int ret;
drv_data = of_device_get_match_data(&pdev->dev);
drv_data = of_device_get_match_data(dev);
if (!drv_data)
return -EINVAL;
regmap = device_node_to_regmap(pdev->dev.of_node);
regmap = device_node_to_regmap(dev->of_node);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
@@ -124,8 +127,7 @@ static int exynos_chipid_probe(struct platform_device *pdev)
if (ret < 0)
return ret;
soc_dev_attr = devm_kzalloc(&pdev->dev, sizeof(*soc_dev_attr),
GFP_KERNEL);
soc_dev_attr = devm_kzalloc(dev, sizeof(*soc_dev_attr), GFP_KERNEL);
if (!soc_dev_attr)
return -ENOMEM;
@@ -135,8 +137,8 @@ static int exynos_chipid_probe(struct platform_device *pdev)
of_property_read_string(root, "model", &soc_dev_attr->machine);
of_node_put(root);
soc_dev_attr->revision = devm_kasprintf(&pdev->dev, GFP_KERNEL,
"%x", soc_info.revision);
soc_dev_attr->revision = devm_kasprintf(dev, GFP_KERNEL, "%x",
soc_info.revision);
if (!soc_dev_attr->revision)
return -ENOMEM;
soc_dev_attr->soc_id = product_id_to_soc_id(soc_info.product_id);
@@ -150,13 +152,13 @@ static int exynos_chipid_probe(struct platform_device *pdev)
if (IS_ERR(soc_dev))
return PTR_ERR(soc_dev);
ret = exynos_asv_init(&pdev->dev, regmap);
ret = exynos_asv_init(dev, regmap);
if (ret)
goto err;
platform_set_drvdata(pdev, soc_dev);
dev_info(&pdev->dev, "Exynos: CPU[%s] PRO_ID[0x%x] REV[0x%x] Detected\n",
dev_info(dev, "Exynos: CPU[%s] PRO_ID[0x%x] REV[0x%x] Detected\n",
soc_dev_attr->soc_id, soc_info.product_id, soc_info.revision);
return 0;

View File

@@ -6,7 +6,6 @@
// Exynos - CPU PMU(Power Management Unit) support
#include <linux/array_size.h>
#include <linux/arm-smccc.h>
#include <linux/bitmap.h>
#include <linux/cpuhotplug.h>
#include <linux/cpu_pm.h>
@@ -25,14 +24,6 @@
#include "exynos-pmu.h"
#define PMUALIVE_MASK GENMASK(13, 0)
#define TENSOR_SET_BITS (BIT(15) | BIT(14))
#define TENSOR_CLR_BITS BIT(15)
#define TENSOR_SMC_PMU_SEC_REG 0x82000504
#define TENSOR_PMUREG_READ 0
#define TENSOR_PMUREG_WRITE 1
#define TENSOR_PMUREG_RMW 2
struct exynos_pmu_context {
struct device *dev;
const struct exynos_pmu_data *pmu_data;
@@ -54,125 +45,6 @@ static struct exynos_pmu_context *pmu_context;
/* forward declaration */
static struct platform_driver exynos_pmu_driver;
/*
* Tensor SoCs are configured so that PMU_ALIVE registers can only be written
* from EL3, but are still read accessible. As Linux needs to write some of
* these registers, the following functions are provided and exposed via
* regmap.
*
* Note: This SMC interface is known to be implemented on gs101 and derivative
* SoCs.
*/
/* Write to a protected PMU register. */
static int tensor_sec_reg_write(void *context, unsigned int reg,
unsigned int val)
{
struct arm_smccc_res res;
unsigned long pmu_base = (unsigned long)context;
arm_smccc_smc(TENSOR_SMC_PMU_SEC_REG, pmu_base + reg,
TENSOR_PMUREG_WRITE, val, 0, 0, 0, 0, &res);
/* returns -EINVAL if access isn't allowed or 0 */
if (res.a0)
pr_warn("%s(): SMC failed: %d\n", __func__, (int)res.a0);
return (int)res.a0;
}
/* Read/Modify/Write a protected PMU register. */
static int tensor_sec_reg_rmw(void *context, unsigned int reg,
unsigned int mask, unsigned int val)
{
struct arm_smccc_res res;
unsigned long pmu_base = (unsigned long)context;
arm_smccc_smc(TENSOR_SMC_PMU_SEC_REG, pmu_base + reg,
TENSOR_PMUREG_RMW, mask, val, 0, 0, 0, &res);
/* returns -EINVAL if access isn't allowed or 0 */
if (res.a0)
pr_warn("%s(): SMC failed: %d\n", __func__, (int)res.a0);
return (int)res.a0;
}
/*
* Read a protected PMU register. All PMU registers can be read by Linux.
* Note: The SMC read register is not used, as only registers that can be
* written are readable via SMC.
*/
static int tensor_sec_reg_read(void *context, unsigned int reg,
unsigned int *val)
{
*val = pmu_raw_readl(reg);
return 0;
}
/*
* For SoCs that have set/clear bit hardware this function can be used when
* the PMU register will be accessed by multiple masters.
*
* For example, to set bits 13:8 in PMU reg offset 0x3e80
* tensor_set_bits_atomic(ctx, 0x3e80, 0x3f00, 0x3f00);
*
* Set bit 8, and clear bits 13:9 PMU reg offset 0x3e80
* tensor_set_bits_atomic(0x3e80, 0x100, 0x3f00);
*/
static int tensor_set_bits_atomic(void *ctx, unsigned int offset, u32 val,
u32 mask)
{
int ret;
unsigned int i;
for (i = 0; i < 32; i++) {
if (!(mask & BIT(i)))
continue;
offset &= ~TENSOR_SET_BITS;
if (val & BIT(i))
offset |= TENSOR_SET_BITS;
else
offset |= TENSOR_CLR_BITS;
ret = tensor_sec_reg_write(ctx, offset, i);
if (ret)
return ret;
}
return 0;
}
static bool tensor_is_atomic(unsigned int reg)
{
/*
* Use atomic operations for PMU_ALIVE registers (offset 0~0x3FFF)
* as the target registers can be accessed by multiple masters. SFRs
* that don't support atomic are added to the switch statement below.
*/
if (reg > PMUALIVE_MASK)
return false;
switch (reg) {
case GS101_SYSIP_DAT0:
case GS101_SYSTEM_CONFIGURATION:
return false;
default:
return true;
}
}
static int tensor_sec_update_bits(void *ctx, unsigned int reg,
unsigned int mask, unsigned int val)
{
if (!tensor_is_atomic(reg))
return tensor_sec_reg_rmw(ctx, reg, mask, val);
return tensor_set_bits_atomic(ctx, reg, val, mask);
}
void pmu_raw_writel(u32 val, u32 offset)
{
writel_relaxed(val, pmu_base_addr + offset);
@@ -244,11 +116,6 @@ static const struct regmap_config regmap_pmu_intr = {
.use_raw_spinlock = true,
};
static const struct exynos_pmu_data gs101_pmu_data = {
.pmu_secure = true,
.pmu_cpuhp = true,
};
/*
* PMU platform driver and devicetree bindings.
*/
@@ -364,6 +231,7 @@ EXPORT_SYMBOL_GPL(exynos_get_pmu_regmap_by_phandle);
* disabled and cpupm_lock held.
*/
static int __gs101_cpu_pmu_online(unsigned int cpu)
__must_hold(&pmu_context->cpupm_lock)
{
unsigned int cpuhint = smp_processor_id();
u32 reg, mask;
@@ -424,6 +292,7 @@ static int gs101_cpuhp_pmu_online(unsigned int cpu)
/* Common function shared by both CPU hot plug and CPUIdle */
static int __gs101_cpu_pmu_offline(unsigned int cpu)
__must_hold(&pmu_context->cpupm_lock)
{
unsigned int cpuhint = smp_processor_id();
u32 reg, mask;
@@ -635,6 +504,9 @@ static int exynos_pmu_probe(struct platform_device *pdev)
pmu_regmcfg = regmap_smccfg;
pmu_regmcfg.max_register = resource_size(res) -
pmu_regmcfg.reg_stride;
pmu_regmcfg.wr_table = pmu_context->pmu_data->wr_table;
pmu_regmcfg.rd_table = pmu_context->pmu_data->rd_table;
/* Need physical address for SMC call */
regmap = devm_regmap_init(dev, NULL,
(void *)(uintptr_t)res->start,

View File

@@ -13,11 +13,38 @@
#define PMU_TABLE_END (-1U)
struct regmap_access_table;
struct exynos_pmu_conf {
unsigned int offset;
u8 val[NUM_SYS_POWERDOWN];
};
/**
* struct exynos_pmu_data - of_device_id (match) data
*
* @pmu_config: Optional table detailing register writes for target system
* states: SYS_AFTR, SYS_LPA, SYS_SLEEP.
* @pmu_config_extra: Optional secondary table detailing additional register
* writes for target system states: SYS_AFTR, SYS_LPA,
* SYS_SLEEP.
* @pmu_secure: Whether or not PMU register writes need to be done via SMC call.
* @pmu_cpuhp: Whether or not extra handling is required for CPU hotplug and
* CPUidle outside of standard PSCI calls, due to non-compliant
* firmware.
* @pmu_init: Optional init function.
* @powerdown_conf: Optional callback before entering target system states:
* SYS_AFTR, SYS_LPA, SYS_SLEEP. This will be invoked before
* the registers from @pmu_config are written.
* @powerdown_conf_extra: Optional secondary callback before entering
* target system states: SYS_AFTR, SYS_LPA, SYS_SLEEP.
* This will be invoked after @pmu_config registers have
* been written.
* @rd_table: A table of readable register ranges in case a custom regmap is
* used (i.e. when @pmu_secure is @true).
* @wr_table: A table of writable register ranges in case a custom regmap is
* used (i.e. when @pmu_secure is @true).
*/
struct exynos_pmu_data {
const struct exynos_pmu_conf *pmu_config;
const struct exynos_pmu_conf *pmu_config_extra;
@@ -27,6 +54,9 @@ struct exynos_pmu_data {
void (*pmu_init)(void);
void (*powerdown_conf)(enum sys_powerdown);
void (*powerdown_conf_extra)(enum sys_powerdown);
const struct regmap_access_table *rd_table;
const struct regmap_access_table *wr_table;
};
extern void __iomem *pmu_base_addr;
@@ -40,7 +70,14 @@ extern const struct exynos_pmu_data exynos4412_pmu_data;
extern const struct exynos_pmu_data exynos5250_pmu_data;
extern const struct exynos_pmu_data exynos5420_pmu_data;
#endif
extern const struct exynos_pmu_data gs101_pmu_data;
extern void pmu_raw_writel(u32 val, u32 offset);
extern u32 pmu_raw_readl(u32 offset);
int tensor_sec_reg_write(void *context, unsigned int reg, unsigned int val);
int tensor_sec_reg_read(void *context, unsigned int reg, unsigned int *val);
int tensor_sec_update_bits(void *context, unsigned int reg, unsigned int mask,
unsigned int val);
#endif /* __EXYNOS_PMU_H */

View File

@@ -0,0 +1,446 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2025 Linaro Ltd.
*
* GS101 PMU (Power Management Unit) support
*/
#include <linux/arm-smccc.h>
#include <linux/array_size.h>
#include <linux/soc/samsung/exynos-pmu.h>
#include <linux/soc/samsung/exynos-regs-pmu.h>
#include <linux/regmap.h>
#include "exynos-pmu.h"
#define PMUALIVE_MASK GENMASK(13, 0)
#define TENSOR_SET_BITS (BIT(15) | BIT(14))
#define TENSOR_CLR_BITS BIT(15)
#define TENSOR_SMC_PMU_SEC_REG 0x82000504
#define TENSOR_PMUREG_READ 0
#define TENSOR_PMUREG_WRITE 1
#define TENSOR_PMUREG_RMW 2
static const struct regmap_range gs101_pmu_registers[] = {
regmap_reg_range(GS101_OM_STAT, GS101_SYSTEM_INFO),
regmap_reg_range(GS101_IDLE_IP(0), GS101_IDLE_IP_MASK(3)),
regmap_reg_range(GS101_DATARAM_STATE_SLC_CH(0),
GS101_PPMPURAM_INFORM_SCL_CH(3)),
regmap_reg_range(GS101_INFORM0, GS101_SYSIP_DAT(0)),
/* skip SYSIP_DAT1 SYSIP_DAT2 */
regmap_reg_range(GS101_SYSIP_DAT(3), GS101_PWR_HOLD_SW_TRIP),
regmap_reg_range(GS101_GSA_INFORM(0), GS101_GSA_INFORM(1)),
regmap_reg_range(GS101_INFORM4, GS101_IROM_INFORM),
regmap_reg_range(GS101_IROM_CPU_INFORM(0), GS101_IROM_CPU_INFORM(7)),
regmap_reg_range(GS101_PMU_SPARE(0), GS101_PMU_SPARE(3)),
/* skip most IROM_xxx registers */
regmap_reg_range(GS101_DREX_CALIBRATION(0), GS101_DREX_CALIBRATION(7)),
#define CLUSTER_CPU_RANGE(cl, cpu) \
regmap_reg_range(GS101_CLUSTER_CPU_CONFIGURATION(cl, cpu), \
GS101_CLUSTER_CPU_OPTION(cl, cpu)), \
regmap_reg_range(GS101_CLUSTER_CPU_OUT(cl, cpu), \
GS101_CLUSTER_CPU_IN(cl, cpu)), \
regmap_reg_range(GS101_CLUSTER_CPU_INT_IN(cl, cpu), \
GS101_CLUSTER_CPU_INT_DIR(cl, cpu))
/* cluster 0..2 and cpu 0..4 or 0..1 */
CLUSTER_CPU_RANGE(GS101_CLUSTER0_OFFSET, 0),
CLUSTER_CPU_RANGE(GS101_CLUSTER0_OFFSET, 1),
CLUSTER_CPU_RANGE(GS101_CLUSTER0_OFFSET, 2),
CLUSTER_CPU_RANGE(GS101_CLUSTER0_OFFSET, 3),
CLUSTER_CPU_RANGE(GS101_CLUSTER1_OFFSET, 0),
CLUSTER_CPU_RANGE(GS101_CLUSTER1_OFFSET, 1),
CLUSTER_CPU_RANGE(GS101_CLUSTER2_OFFSET, 0),
CLUSTER_CPU_RANGE(GS101_CLUSTER2_OFFSET, 1),
#undef CLUSTER_CPU_RANGE
#define CLUSTER_NONCPU_RANGE(cl) \
regmap_reg_range(GS101_CLUSTER_NONCPU_CONFIGURATION(cl), \
GS101_CLUSTER_NONCPU_OPTION(cl)), \
regmap_reg_range(GS101_CLUSTER_NONCPU_OUT(cl), \
GS101_CLUSTER_NONCPU_IN(cl)), \
regmap_reg_range(GS101_CLUSTER_NONCPU_INT_IN(cl), \
GS101_CLUSTER_NONCPU_INT_DIR(cl)), \
regmap_reg_range(GS101_CLUSTER_NONCPU_DUALRAIL_CTRL_OUT(cl), \
GS101_CLUSTER_NONCPU_DUALRAIL_POS_OUT(cl)), \
regmap_reg_range(GS101_CLUSTER_NONCPU_DUALRAIL_CTRL_IN(cl), \
GS101_CLUSTER_NONCPU_DUALRAIL_CTRL_IN(cl))
CLUSTER_NONCPU_RANGE(0),
regmap_reg_range(GS101_CLUSTER0_NONCPU_DSU_PCH,
GS101_CLUSTER0_NONCPU_DSU_PCH),
CLUSTER_NONCPU_RANGE(1),
CLUSTER_NONCPU_RANGE(2),
#undef CLUSTER_NONCPU_RANGE
#define SUBBLK_RANGE(blk) \
regmap_reg_range(GS101_SUBBLK_CONFIGURATION(blk), \
GS101_SUBBLK_CTRL(blk)), \
regmap_reg_range(GS101_SUBBLK_OUT(blk), GS101_SUBBLK_IN(blk)), \
regmap_reg_range(GS101_SUBBLK_INT_IN(blk), \
GS101_SUBBLK_INT_DIR(blk)), \
regmap_reg_range(GS101_SUBBLK_MEMORY_OUT(blk), \
GS101_SUBBLK_MEMORY_IN(blk))
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_ALIVE),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_AOC),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_APM),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_CMU),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_BUS0),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_BUS1),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_BUS2),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_CORE),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_EH),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_CPUCL0),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_CPUCL1),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_CPUCL2),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_G3D),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_EMBEDDED_CPUCL0),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_EMBEDDED_G3D),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_HSI0),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_HSI1),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_HSI2),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_DPU),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_DISP),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_G2D),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_MFC),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_CSIS),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_PDP),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_DNS),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_G3AA),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_IPP),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_ITP),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_MCSC),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_GDC),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_TNR),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_BO),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_TPU),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_MIF0),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_MIF1),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_MIF2),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_MIF3),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_MISC),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_PERIC0),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_PERIC1),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_S2D),
#undef SUBBLK_RANGE
#define SUBBLK_CPU_RANGE(blk) \
regmap_reg_range(GS101_SUBBLK_CPU_CONFIGURATION(blk), \
GS101_SUBBLK_CPU_OPTION(blk)), \
regmap_reg_range(GS101_SUBBLK_CPU_OUT(blk), \
GS101_SUBBLK_CPU_IN(blk)), \
regmap_reg_range(GS101_SUBBLK_CPU_INT_IN(blk), \
GS101_SUBBLK_CPU_INT_DIR(blk))
SUBBLK_CPU_RANGE(GS101_SUBBBLK_CPU_OFFSET_APM),
SUBBLK_CPU_RANGE(GS101_SUBBBLK_CPU_OFFSET_DBGCORE),
SUBBLK_CPU_RANGE(GS101_SUBBBLK_CPU_OFFSET_SSS),
#undef SUBBLK_CPU_RANGE
regmap_reg_range(GS101_MIF_CONFIGURATION, GS101_MIF_CTRL),
regmap_reg_range(GS101_MIF_OUT, GS101_MIF_IN),
regmap_reg_range(GS101_MIF_INT_IN, GS101_MIF_INT_DIR),
regmap_reg_range(GS101_TOP_CONFIGURATION, GS101_TOP_OPTION),
regmap_reg_range(GS101_TOP_OUT, GS101_TOP_IN),
regmap_reg_range(GS101_TOP_INT_IN, GS101_WAKEUP2_STAT),
regmap_reg_range(GS101_WAKEUP2_INT_IN, GS101_WAKEUP2_INT_DIR),
regmap_reg_range(GS101_SYSTEM_CONFIGURATION, GS101_USER_DEFINED_OUT),
regmap_reg_range(GS101_SYSTEM_OUT, GS101_SYSTEM_IN),
regmap_reg_range(GS101_SYSTEM_INT_IN, GS101_EINT_WAKEUP_MASK3),
regmap_reg_range(GS101_USER_DEFINED_INT_IN, GS101_SCAN2DRAM_INT_DIR),
/* skip HCU_START */
regmap_reg_range(GS101_CUSTOM_OUT, GS101_CUSTOM_IN),
regmap_reg_range(GS101_CUSTOM_INT_IN, GS101_CUSTOM_INT_DIR),
regmap_reg_range(GS101_ACK_LAST_CPU, GS101_HCU_R(3)),
regmap_reg_range(GS101_HCU_SP, GS101_HCU_PC),
/* skip PMU_RAM_CTRL */
regmap_reg_range(GS101_APM_HCU_CTRL, GS101_APM_HCU_CTRL),
regmap_reg_range(GS101_APM_NMI_ENABLE, GS101_RST_STAT_PMU),
regmap_reg_range(GS101_HPM_INT_IN, GS101_BOOT_STAT),
regmap_reg_range(GS101_PMLINK_OUT, GS101_PMLINK_AOC_CTRL),
regmap_reg_range(GS101_TCXO_BUF_CTRL, GS101_ADD_CTRL),
regmap_reg_range(GS101_HCU_TIMEOUT_RESET, GS101_HCU_TIMEOUT_SCAN2DRAM),
regmap_reg_range(GS101_TIMER(0), GS101_TIMER(3)),
regmap_reg_range(GS101_PPC_MIF(0), GS101_PPC_EH),
/* PPC_OFFSET, skip PPC_CPUCL1_0 PPC_CPUCL1_1 */
regmap_reg_range(GS101_EXT_REGULATOR_MIF_DURATION, GS101_TCXO_DURATION),
regmap_reg_range(GS101_BURNIN_CTRL, GS101_TMU_SUB_TRIP),
regmap_reg_range(GS101_MEMORY_CEN, GS101_MEMORY_SMX_FEEDBACK),
regmap_reg_range(GS101_SLC_PCH_CHANNEL, GS101_SLC_PCH_CB),
regmap_reg_range(GS101_FORCE_NOMC, GS101_FORCE_NOMC),
regmap_reg_range(GS101_FORCE_BOOST, GS101_PMLINK_SLC_BUSY),
regmap_reg_range(GS101_BOOTSYNC_OUT, GS101_CTRL_SECJTAG_ALIVE),
regmap_reg_range(GS101_CTRL_DIV_PLL_ALV_DIVLOW, GS101_CTRL_CLKDIV__CLKRTC),
regmap_reg_range(GS101_CTRL_SOC32K, GS101_CTRL_SBU_SW_EN),
regmap_reg_range(GS101_PAD_CTRL_CLKOUT0, GS101_PAD_CTRL_WRESETO_n),
regmap_reg_range(GS101_PHY_CTRL_USB20, GS101_PHY_CTRL_UFS),
};
static const struct regmap_range gs101_pmu_ro_registers[] = {
regmap_reg_range(GS101_OM_STAT, GS101_VERSION),
regmap_reg_range(GS101_OTP_STATUS, GS101_OTP_STATUS),
regmap_reg_range(GS101_DATARAM_STATE_SLC_CH(0),
GS101_PPMPURAM_STATE_SLC_CH(0)),
regmap_reg_range(GS101_DATARAM_STATE_SLC_CH(1),
GS101_PPMPURAM_STATE_SLC_CH(1)),
regmap_reg_range(GS101_DATARAM_STATE_SLC_CH(2),
GS101_PPMPURAM_STATE_SLC_CH(2)),
regmap_reg_range(GS101_DATARAM_STATE_SLC_CH(3),
GS101_PPMPURAM_STATE_SLC_CH(3)),
#define CLUSTER_CPU_RANGE(cl, cpu) \
regmap_reg_range(GS101_CLUSTER_CPU_IN(cl, cpu), \
GS101_CLUSTER_CPU_IN(cl, cpu)), \
regmap_reg_range(GS101_CLUSTER_CPU_INT_IN(cl, cpu), \
GS101_CLUSTER_CPU_INT_IN(cl, cpu))
CLUSTER_CPU_RANGE(GS101_CLUSTER0_OFFSET, 0),
CLUSTER_CPU_RANGE(GS101_CLUSTER0_OFFSET, 1),
CLUSTER_CPU_RANGE(GS101_CLUSTER0_OFFSET, 2),
CLUSTER_CPU_RANGE(GS101_CLUSTER0_OFFSET, 3),
CLUSTER_CPU_RANGE(GS101_CLUSTER1_OFFSET, 0),
CLUSTER_CPU_RANGE(GS101_CLUSTER1_OFFSET, 1),
CLUSTER_CPU_RANGE(GS101_CLUSTER2_OFFSET, 0),
CLUSTER_CPU_RANGE(GS101_CLUSTER2_OFFSET, 1),
#undef CLUSTER_CPU_RANGE
#define CLUSTER_NONCPU_RANGE(cl) \
regmap_reg_range(GS101_CLUSTER_NONCPU_IN(cl), \
GS101_CLUSTER_NONCPU_IN(cl)), \
regmap_reg_range(GS101_CLUSTER_NONCPU_INT_IN(cl), \
GS101_CLUSTER_NONCPU_INT_IN(cl)), \
regmap_reg_range(GS101_CLUSTER_NONCPU_DUALRAIL_CTRL_IN(cl), \
GS101_CLUSTER_NONCPU_DUALRAIL_CTRL_IN(cl))
CLUSTER_NONCPU_RANGE(0),
CLUSTER_NONCPU_RANGE(1),
CLUSTER_NONCPU_RANGE(2),
regmap_reg_range(GS101_CLUSTER_NONCPU_INT_EN(2),
GS101_CLUSTER_NONCPU_INT_DIR(2)),
#undef CLUSTER_NONCPU_RANGE
#define SUBBLK_RANGE(blk) \
regmap_reg_range(GS101_SUBBLK_IN(blk), GS101_SUBBLK_IN(blk)), \
regmap_reg_range(GS101_SUBBLK_INT_IN(blk), \
GS101_SUBBLK_INT_IN(blk)), \
regmap_reg_range(GS101_SUBBLK_MEMORY_IN(blk), \
GS101_SUBBLK_MEMORY_IN(blk))
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_ALIVE),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_AOC),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_APM),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_CMU),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_BUS0),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_BUS1),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_BUS2),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_CORE),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_EH),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_CPUCL0),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_CPUCL1),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_CPUCL2),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_G3D),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_EMBEDDED_CPUCL0),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_EMBEDDED_G3D),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_HSI0),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_HSI1),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_HSI2),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_DPU),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_DISP),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_G2D),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_MFC),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_CSIS),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_PDP),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_DNS),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_G3AA),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_IPP),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_ITP),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_MCSC),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_GDC),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_TNR),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_BO),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_TPU),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_MIF0),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_MIF1),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_MIF2),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_MIF3),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_MISC),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_PERIC0),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_PERIC1),
SUBBLK_RANGE(GS101_SUBBBLK_OFFSET_S2D),
#undef SUBBLK_RANGE
#define SUBBLK_CPU_RANGE(blk) \
regmap_reg_range(GS101_SUBBLK_CPU_IN(blk), \
GS101_SUBBLK_CPU_IN(blk)), \
regmap_reg_range(GS101_SUBBLK_CPU_INT_IN(blk), \
GS101_SUBBLK_CPU_INT_IN(blk))
SUBBLK_CPU_RANGE(GS101_SUBBBLK_CPU_OFFSET_APM),
SUBBLK_CPU_RANGE(GS101_SUBBBLK_CPU_OFFSET_DBGCORE),
SUBBLK_CPU_RANGE(GS101_SUBBBLK_CPU_OFFSET_SSS),
#undef SUBBLK_CPU_RANGE
regmap_reg_range(GS101_MIF_CONFIGURATION, GS101_MIF_CONFIGURATION),
regmap_reg_range(GS101_MIF_IN, GS101_MIF_IN),
regmap_reg_range(GS101_MIF_INT_IN, GS101_MIF_INT_IN),
regmap_reg_range(GS101_TOP_IN, GS101_TOP_IN),
regmap_reg_range(GS101_TOP_INT_IN, GS101_TOP_INT_IN),
regmap_reg_range(GS101_WAKEUP2_INT_IN, GS101_WAKEUP2_INT_IN),
regmap_reg_range(GS101_SYSTEM_IN, GS101_SYSTEM_IN),
regmap_reg_range(GS101_SYSTEM_INT_IN, GS101_SYSTEM_INT_IN),
regmap_reg_range(GS101_EINT_INT_IN, GS101_EINT_INT_IN),
regmap_reg_range(GS101_EINT2_INT_IN, GS101_EINT2_INT_IN),
regmap_reg_range(GS101_EINT3_INT_IN, GS101_EINT3_INT_IN),
regmap_reg_range(GS101_USER_DEFINED_INT_IN, GS101_USER_DEFINED_INT_IN),
regmap_reg_range(GS101_SCAN2DRAM_INT_IN, GS101_SCAN2DRAM_INT_IN),
regmap_reg_range(GS101_CUSTOM_IN, GS101_CUSTOM_IN),
regmap_reg_range(GS101_CUSTOM_INT_IN, GS101_CUSTOM_INT_IN),
regmap_reg_range(GS101_HCU_R(0), GS101_HCU_R(3)),
regmap_reg_range(GS101_HCU_SP, GS101_HCU_PC),
regmap_reg_range(GS101_NMI_SRC_IN, GS101_NMI_SRC_IN),
regmap_reg_range(GS101_HPM_INT_IN, GS101_HPM_INT_IN),
regmap_reg_range(GS101_MEMORY_PGEN_FEEDBACK, GS101_MEMORY_PGEN_FEEDBACK),
regmap_reg_range(GS101_MEMORY_SMX_FEEDBACK, GS101_MEMORY_SMX_FEEDBACK),
regmap_reg_range(GS101_PMLINK_SLC_ACK, GS101_PMLINK_SLC_BUSY),
regmap_reg_range(GS101_BOOTSYNC_IN, GS101_BOOTSYNC_IN),
regmap_reg_range(GS101_SCAN_READY_IN, GS101_SCAN_READY_IN),
regmap_reg_range(GS101_CTRL_PLL_ALV_LOCK, GS101_CTRL_PLL_ALV_LOCK),
};
static const struct regmap_access_table gs101_pmu_rd_table = {
.yes_ranges = gs101_pmu_registers,
.n_yes_ranges = ARRAY_SIZE(gs101_pmu_registers),
};
static const struct regmap_access_table gs101_pmu_wr_table = {
.yes_ranges = gs101_pmu_registers,
.n_yes_ranges = ARRAY_SIZE(gs101_pmu_registers),
.no_ranges = gs101_pmu_ro_registers,
.n_no_ranges = ARRAY_SIZE(gs101_pmu_ro_registers),
};
const struct exynos_pmu_data gs101_pmu_data = {
.pmu_secure = true,
.pmu_cpuhp = true,
.rd_table = &gs101_pmu_rd_table,
.wr_table = &gs101_pmu_wr_table,
};
/*
* Tensor SoCs are configured so that PMU_ALIVE registers can only be written
* from EL3, but are still read accessible. As Linux needs to write some of
* these registers, the following functions are provided and exposed via
* regmap.
*
* Note: This SMC interface is known to be implemented on gs101 and derivative
* SoCs.
*/
/* Write to a protected PMU register. */
int tensor_sec_reg_write(void *context, unsigned int reg, unsigned int val)
{
struct arm_smccc_res res;
unsigned long pmu_base = (unsigned long)context;
arm_smccc_smc(TENSOR_SMC_PMU_SEC_REG, pmu_base + reg,
TENSOR_PMUREG_WRITE, val, 0, 0, 0, 0, &res);
/* returns -EINVAL if access isn't allowed or 0 */
if (res.a0)
pr_warn("%s(): SMC failed: %d\n", __func__, (int)res.a0);
return (int)res.a0;
}
/* Read/Modify/Write a protected PMU register. */
static int tensor_sec_reg_rmw(void *context, unsigned int reg,
unsigned int mask, unsigned int val)
{
struct arm_smccc_res res;
unsigned long pmu_base = (unsigned long)context;
arm_smccc_smc(TENSOR_SMC_PMU_SEC_REG, pmu_base + reg,
TENSOR_PMUREG_RMW, mask, val, 0, 0, 0, &res);
/* returns -EINVAL if access isn't allowed or 0 */
if (res.a0)
pr_warn("%s(): SMC failed: %d\n", __func__, (int)res.a0);
return (int)res.a0;
}
/*
* Read a protected PMU register. All PMU registers can be read by Linux.
* Note: The SMC read register is not used, as only registers that can be
* written are readable via SMC.
*/
int tensor_sec_reg_read(void *context, unsigned int reg, unsigned int *val)
{
*val = pmu_raw_readl(reg);
return 0;
}
/*
* For SoCs that have set/clear bit hardware this function can be used when
* the PMU register will be accessed by multiple masters.
*
* For example, to set bits 13:8 in PMU reg offset 0x3e80
* tensor_set_bits_atomic(ctx, 0x3e80, 0x3f00, 0x3f00);
*
* Set bit 8, and clear bits 13:9 PMU reg offset 0x3e80
* tensor_set_bits_atomic(0x3e80, 0x100, 0x3f00);
*/
static int tensor_set_bits_atomic(void *context, unsigned int offset, u32 val,
u32 mask)
{
int ret;
unsigned int i;
for (i = 0; i < 32; i++) {
if (!(mask & BIT(i)))
continue;
offset &= ~TENSOR_SET_BITS;
if (val & BIT(i))
offset |= TENSOR_SET_BITS;
else
offset |= TENSOR_CLR_BITS;
ret = tensor_sec_reg_write(context, offset, i);
if (ret)
return ret;
}
return 0;
}
static bool tensor_is_atomic(unsigned int reg)
{
/*
* Use atomic operations for PMU_ALIVE registers (offset 0~0x3FFF)
* as the target registers can be accessed by multiple masters. SFRs
* that don't support atomic are added to the switch statement below.
*/
if (reg > PMUALIVE_MASK)
return false;
switch (reg) {
case GS101_SYSIP_DAT(0):
case GS101_SYSTEM_CONFIGURATION:
return false;
default:
return true;
}
}
int tensor_sec_update_bits(void *context, unsigned int reg, unsigned int mask,
unsigned int val)
{
if (!tensor_is_atomic(reg))
return tensor_sec_reg_rmw(context, reg, mask, val);
return tensor_set_bits_atomic(context, reg, val, mask);
}

View File

@@ -672,14 +672,341 @@
/* For Tensor GS101 */
/* PMU ALIVE */
#define GS101_SYSIP_DAT0 (0x810)
#define GS101_CPU0_INFORM (0x860)
#define GS101_CPU_INFORM(cpu) \
(GS101_CPU0_INFORM + (cpu*4))
#define GS101_SYSTEM_CONFIGURATION (0x3A00)
#define GS101_EINT_WAKEUP_MASK (0x3A80)
#define GS101_PHY_CTRL_USB20 (0x3EB0)
#define GS101_PHY_CTRL_USBDP (0x3EB4)
#define GS101_OM_STAT 0x0000
#define GS101_VERSION 0x0004
#define GS101_PORESET_CHECK 0x0008
#define GS101_OTP_STATUS 0x000c
#define GS101_SYSTEM_INFO 0x0010
#define GS101_IDLE_IP(n) (0x03e0 + ((n) & 3) * 4)
#define GS101_IDLE_IP_MASK(n) (0x03f0 + ((n) & 3) * 4)
#define GS101_SLC_CH_OFFSET(ch) (0x0400 + ((ch) & 3) * 0x10)
#define GS101_DATARAM_STATE_SLC_CH(ch) (GS101_SLC_CH_OFFSET(ch) + 0x00)
#define GS101_TAGRAM_STATE_SLC_CH(ch) (GS101_SLC_CH_OFFSET(ch) + 0x04)
#define GS101_LRURAM_STATE_SLC_CH(ch) (GS101_SLC_CH_OFFSET(ch) + 0x08)
#define GS101_PPMPURAM_STATE_SLC_CH(ch) (GS101_SLC_CH_OFFSET(ch) + 0x0c)
#define GS101_DATARAM_INFORM_SCL_CH(ch) (GS101_SLC_CH_OFFSET(ch) + 0x40)
#define GS101_TAGRAM_INFORM_SCL_CH(ch) (GS101_SLC_CH_OFFSET(ch) + 0x44)
#define GS101_LRURAM_INFORM_SCL_CH(ch) (GS101_SLC_CH_OFFSET(ch) + 0x48)
#define GS101_PPMPURAM_INFORM_SCL_CH(ch) (GS101_SLC_CH_OFFSET(ch) + 0x4c)
#define GS101_INFORM0 0x0800
#define GS101_INFORM1 0x0804
#define GS101_INFORM2 0x0808
#define GS101_INFORM3 0x080c
#define GS101_SYSIP_DAT(n) (0x0810 + ((n) & 3) * 4)
#define GS101_PWR_HOLD_HW_TRIP 0x0820
#define GS101_PWR_HOLD_SW_TRIP 0x0824
#define GS101_GSA_INFORM(n) (0x0830 + ((n) & 1) * 4)
#define GS101_INFORM4 0x0840
#define GS101_INFORM5 0x0844
#define GS101_INFORM6 0x0848
#define GS101_INFORM7 0x084c
#define GS101_INFORM8 0x0850
#define GS101_INFORM9 0x0854
#define GS101_INFORM10 0x0858
#define GS101_INFORM11 0x085c
#define GS101_CPU_INFORM(cpu) (0x0860 + ((cpu) & 7) * 4)
#define GS101_IROM_INFORM 0x0880
#define GS101_IROM_CPU_INFORM(cpu) (0x0890 + ((cpu) & 7) * 4)
#define GS101_PMU_SPARE(n) (0x0900 + ((n) & 3) * 4)
#define GS101_IROM_DATA_REG(n) (0x0980 + ((n) & 3) * 4)
#define GS101_IROM_PWRMODE 0x0990
#define GS101_DREX_CALIBRATION(n) (0x09a0 + ((n) & 7) * 4)
#define GS101_CLUSTER0_OFFSET 0x1000
#define GS101_CLUSTER1_OFFSET 0x1300
#define GS101_CLUSTER2_OFFSET 0x1500
#define GS101_CLUSTER_CPU_OFFSET(cl, cpu) ((cl) + ((cpu) * 0x80))
#define GS101_CLUSTER_CPU_CONFIGURATION(cl, cpu) \
(GS101_CLUSTER_CPU_OFFSET(cl, cpu) + 0x00)
#define GS101_CLUSTER_CPU_STATUS(cl, cpu) \
(GS101_CLUSTER_CPU_OFFSET(cl, cpu) + 0x04)
#define GS101_CLUSTER_CPU_STATES(cl, cpu) \
(GS101_CLUSTER_CPU_OFFSET(cl, cpu) + 0x08)
#define GS101_CLUSTER_CPU_OPTION(cl, cpu) \
(GS101_CLUSTER_CPU_OFFSET(cl, cpu) + 0x0c)
#define GS101_CLUSTER_CPU_OUT(cl, cpu) \
(GS101_CLUSTER_CPU_OFFSET(cl, cpu) + 0x20)
#define GS101_CLUSTER_CPU_IN(cl, cpu) \
(GS101_CLUSTER_CPU_OFFSET(cl, cpu) + 0x24)
#define GS101_CLUSTER_CPU_INT_IN(cl, cpu) \
(GS101_CLUSTER_CPU_OFFSET(cl, cpu) + 0x40)
#define GS101_CLUSTER_CPU_INT_EN(cl, cpu) \
(GS101_CLUSTER_CPU_OFFSET(cl, cpu) + 0x44)
#define GS101_CLUSTER_CPU_INT_TYPE(cl, cpu) \
(GS101_CLUSTER_CPU_OFFSET(cl, cpu) + 0x48)
#define GS101_CLUSTER_CPU_INT_DIR(cl, cpu) \
(GS101_CLUSTER_CPU_OFFSET(cl, cpu) + 0x4c)
#define GS101_CLUSTER_NONCPU_OFFSET(cl) (0x1200 + ((cl) * 0x200))
#define GS101_CLUSTER_NONCPU_CONFIGURATION(cl) \
(GS101_CLUSTER_NONCPU_OFFSET(cl) + 0x00)
#define GS101_CLUSTER_NONCPU_STATUS(cl) \
(GS101_CLUSTER_NONCPU_OFFSET(cl) + 0x04)
#define GS101_CLUSTER_NONCPU_STATES(cl) \
(GS101_CLUSTER_NONCPU_OFFSET(cl) + 0x08)
#define GS101_CLUSTER_NONCPU_OPTION(cl) \
(GS101_CLUSTER_NONCPU_OFFSET(cl) + 0x0c)
#define GS101_CLUSTER_NONCPU_OUT(cl) \
(GS101_CLUSTER_NONCPU_OFFSET(cl) + 0x20)
#define GS101_CLUSTER_NONCPU_IN(cl) \
(GS101_CLUSTER_NONCPU_OFFSET(cl) + 0x24)
#define GS101_CLUSTER_NONCPU_INT_IN(cl) \
(GS101_CLUSTER_NONCPU_OFFSET(cl) + 0x40)
#define GS101_CLUSTER_NONCPU_INT_EN(cl) \
(GS101_CLUSTER_NONCPU_OFFSET(cl) + 0x44)
#define GS101_CLUSTER_NONCPU_INT_TYPE(cl) \
(GS101_CLUSTER_NONCPU_OFFSET(cl) + 0x48)
#define GS101_CLUSTER_NONCPU_INT_DIR(cl) \
(GS101_CLUSTER_NONCPU_OFFSET(cl) + 0x4c)
#define GS101_CLUSTER_NONCPU_DUALRAIL_CTRL_OUT(cl) \
(GS101_CLUSTER_NONCPU_OFFSET(cl) + 0x60)
#define GS101_CLUSTER_NONCPU_DUALRAIL_POS_OUT(cl) \
(GS101_CLUSTER_NONCPU_OFFSET(cl) + 0x64)
#define GS101_CLUSTER_NONCPU_DUALRAIL_CTRL_IN(cl) \
(GS101_CLUSTER_NONCPU_OFFSET(cl) + 0x6c)
#define GS101_CLUSTER0_NONCPU_DSU_PCH \
(GS101_CLUSTER_NONCPU_OFFSET(0) + 0x80)
#define GS101_SUBBBLK_OFFSET_ALIVE 0x1800
#define GS101_SUBBBLK_OFFSET_AOC 0x1880
#define GS101_SUBBBLK_OFFSET_APM 0x1900
#define GS101_SUBBBLK_OFFSET_CMU 0x1980
#define GS101_SUBBBLK_OFFSET_BUS0 0x1a00
#define GS101_SUBBBLK_OFFSET_BUS1 0x1a80
#define GS101_SUBBBLK_OFFSET_BUS2 0x1b00
#define GS101_SUBBBLK_OFFSET_CORE 0x1b80
#define GS101_SUBBBLK_OFFSET_EH 0x1c00
#define GS101_SUBBBLK_OFFSET_CPUCL0 0x1c80
#define GS101_SUBBBLK_OFFSET_CPUCL1 0x1d00
#define GS101_SUBBBLK_OFFSET_CPUCL2 0x1d80
#define GS101_SUBBBLK_OFFSET_G3D 0x1e00
#define GS101_SUBBBLK_OFFSET_EMBEDDED_CPUCL0 0x1e80
#define GS101_SUBBBLK_OFFSET_EMBEDDED_G3D 0x2000
#define GS101_SUBBBLK_OFFSET_HSI0 0x2080
#define GS101_SUBBBLK_OFFSET_HSI1 0x2100
#define GS101_SUBBBLK_OFFSET_HSI2 0x2180
#define GS101_SUBBBLK_OFFSET_DPU 0x2200
#define GS101_SUBBBLK_OFFSET_DISP 0x2280
#define GS101_SUBBBLK_OFFSET_G2D 0x2300
#define GS101_SUBBBLK_OFFSET_MFC 0x2380
#define GS101_SUBBBLK_OFFSET_CSIS 0x2400
#define GS101_SUBBBLK_OFFSET_PDP 0x2480
#define GS101_SUBBBLK_OFFSET_DNS 0x2500
#define GS101_SUBBBLK_OFFSET_G3AA 0x2580
#define GS101_SUBBBLK_OFFSET_IPP 0x2600
#define GS101_SUBBBLK_OFFSET_ITP 0x2680
#define GS101_SUBBBLK_OFFSET_MCSC 0x2700
#define GS101_SUBBBLK_OFFSET_GDC 0x2780
#define GS101_SUBBBLK_OFFSET_TNR 0x2800
#define GS101_SUBBBLK_OFFSET_BO 0x2880
#define GS101_SUBBBLK_OFFSET_TPU 0x2900
#define GS101_SUBBBLK_OFFSET_MIF0 0x2980
#define GS101_SUBBBLK_OFFSET_MIF1 0x2a00
#define GS101_SUBBBLK_OFFSET_MIF2 0x2a80
#define GS101_SUBBBLK_OFFSET_MIF3 0x2b00
#define GS101_SUBBBLK_OFFSET_MISC 0x2b80
#define GS101_SUBBBLK_OFFSET_PERIC0 0x2c00
#define GS101_SUBBBLK_OFFSET_PERIC1 0x2c80
#define GS101_SUBBBLK_OFFSET_S2D 0x2d00
#define GS101_SUBBLK_CONFIGURATION(blk) ((blk) + 0x00)
#define GS101_SUBBLK_STATUS(blk) ((blk) + 0x04)
#define GS101_SUBBLK_STATES(blk) ((blk) + 0x08)
#define GS101_SUBBLK_OPTION(blk) ((blk) + 0x0c)
#define GS101_SUBBLK_CTRL(blk) ((blk) + 0x10)
#define GS101_SUBBLK_OUT(blk) ((blk) + 0x20)
#define GS101_SUBBLK_IN(blk) ((blk) + 0x24)
#define GS101_SUBBLK_INT_IN(blk) ((blk) + 0x40)
#define GS101_SUBBLK_INT_EN(blk) ((blk) + 0x44)
#define GS101_SUBBLK_INT_TYPE(blk) ((blk) + 0x48)
#define GS101_SUBBLK_INT_DIR(blk) ((blk) + 0x4c)
#define GS101_SUBBLK_MEMORY_OUT(blk) ((blk) + 0x60)
#define GS101_SUBBLK_MEMORY_IN(blk) ((blk) + 0x64)
#define GS101_SUBBBLK_CPU_OFFSET_APM 0x3000
#define GS101_SUBBBLK_CPU_OFFSET_DBGCORE 0x3080
#define GS101_SUBBBLK_CPU_OFFSET_SSS 0x3100
#define GS101_SUBBLK_CPU_CONFIGURATION(blk) ((blk) + 0x00)
#define GS101_SUBBLK_CPU_STATUS(blk) ((blk) + 0x04)
#define GS101_SUBBLK_CPU_STATES(blk) ((blk) + 0x08)
#define GS101_SUBBLK_CPU_OPTION(blk) ((blk) + 0x0c)
#define GS101_SUBBLK_CPU_OUT(blk) ((blk) + 0x20)
#define GS101_SUBBLK_CPU_IN(blk) ((blk) + 0x24)
#define GS101_SUBBLK_CPU_INT_IN(blk) ((blk) + 0x40)
#define GS101_SUBBLK_CPU_INT_EN(blk) ((blk) + 0x44)
#define GS101_SUBBLK_CPU_INT_TYPE(blk) ((blk) + 0x48)
#define GS101_SUBBLK_CPU_INT_DIR(blk) ((blk) + 0x4c)
#define GS101_MIF_CONFIGURATION 0x3800
#define GS101_MIF_STATUS 0x3804
#define GS101_MIF_STATES 0x3808
#define GS101_MIF_OPTION 0x380c
#define GS101_MIF_CTRL 0x3810
#define GS101_MIF_OUT 0x3820
#define GS101_MIF_IN 0x3824
#define GS101_MIF_INT_IN 0x3840
#define GS101_MIF_INT_EN 0x3844
#define GS101_MIF_INT_TYPE 0x3848
#define GS101_MIF_INT_DIR 0x384c
#define GS101_TOP_CONFIGURATION 0x3900
#define GS101_TOP_STATUS 0x3904
#define GS101_TOP_STATES 0x3908
#define GS101_TOP_OPTION 0x390c
#define GS101_TOP_OUT 0x3920
#define GS101_TOP_IN 0x3924
#define GS101_TOP_INT_IN 0x3940
#define GS101_TOP_INT_EN 0x3944
#define GS101_TOP_INT_TYPE 0x3948
#define GS101_TOP_INT_DIR 0x394c
#define GS101_WAKEUP_STAT 0x3950
#define GS101_WAKEUP2_STAT 0x3954
#define GS101_WAKEUP2_INT_IN 0x3960
#define GS101_WAKEUP2_INT_EN 0x3964
#define GS101_WAKEUP2_INT_TYPE 0x3968
#define GS101_WAKEUP2_INT_DIR 0x396c
#define GS101_SYSTEM_CONFIGURATION 0x3a00
#define GS101_SYSTEM_STATUS 0x3a04
#define GS101_SYSTEM_STATES 0x3a08
#define GS101_SYSTEM_OPTION 0x3a0c
#define GS101_SYSTEM_CTRL 0x3a10
#define GS101_SPARE_CTRL 0x3a14
#define GS101_USER_DEFINED_OUT 0x3a18
#define GS101_SYSTEM_OUT 0x3a20
#define GS101_SYSTEM_IN 0x3a24
#define GS101_SYSTEM_INT_IN 0x3a40
#define GS101_SYSTEM_INT_EN 0x3a44
#define GS101_SYSTEM_INT_TYPE 0x3a48
#define GS101_SYSTEM_INT_DIR 0x3a4c
#define GS101_EINT_INT_IN 0x3a50
#define GS101_EINT_INT_EN 0x3a54
#define GS101_EINT_INT_TYPE 0x3a58
#define GS101_EINT_INT_DIR 0x3a5c
#define GS101_EINT2_INT_IN 0x3a60
#define GS101_EINT2_INT_EN 0x3a64
#define GS101_EINT2_INT_TYPE 0x3a68
#define GS101_EINT2_INT_DIR 0x3a6c
#define GS101_EINT3_INT_IN 0x3a70
#define GS101_EINT3_INT_EN 0x3a74
#define GS101_EINT3_INT_TYPE 0x3a78
#define GS101_EINT3_INT_DIR 0x3a7c
#define GS101_EINT_WAKEUP_MASK 0x3a80
#define GS101_EINT_WAKEUP_MASK2 0x3a84
#define GS101_EINT_WAKEUP_MASK3 0x3a88
#define GS101_USER_DEFINED_INT_IN 0x3a90
#define GS101_USER_DEFINED_INT_EN 0x3a94
#define GS101_USER_DEFINED_INT_TYPE 0x3a98
#define GS101_USER_DEFINED_INT_DIR 0x3a9c
#define GS101_SCAN2DRAM_INT_IN 0x3aa0
#define GS101_SCAN2DRAM_INT_EN 0x3aa4
#define GS101_SCAN2DRAM_INT_TYPE 0x3aa8
#define GS101_SCAN2DRAM_INT_DIR 0x3aac
#define GS101_HCU_START 0x3ab0
#define GS101_CUSTOM_OUT 0x3ac0
#define GS101_CUSTOM_IN 0x3ac4
#define GS101_CUSTOM_INT_IN 0x3ad0
#define GS101_CUSTOM_INT_EN 0x3ad4
#define GS101_CUSTOM_INT_TYPE 0x3ad8
#define GS101_CUSTOM_INT_DIR 0x3adc
#define GS101_ACK_LAST_CPU 0x3afc
#define GS101_HCU_R(n) (0x3b00 + ((n) & 3) * 4)
#define GS101_HCU_SP 0x3b14
#define GS101_HCU_PC 0x3b18
#define GS101_PMU_RAM_CTRL 0x3b20
#define GS101_APM_HCU_CTRL 0x3b24
#define GS101_APM_NMI_ENABLE 0x3b30
#define GS101_DBGCORE_NMI_ENABLE 0x3b34
#define GS101_HCU_NMI_ENABLE 0x3b38
#define GS101_PWR_HOLD_WDT_ENABLE 0x3b3c
#define GS101_NMI_SRC_IN 0x3b40
#define GS101_RST_STAT 0x3b44
#define GS101_RST_STAT_PMU 0x3b48
#define GS101_HPM_INT_IN 0x3b60
#define GS101_HPM_INT_EN 0x3b64
#define GS101_HPM_INT_TYPE 0x3b68
#define GS101_HPM_INT_DIR 0x3b6c
#define GS101_S2D_AUTH 0x3b70
#define GS101_BOOT_STAT 0x3b74
#define GS101_PMLINK_OUT 0x3c00
#define GS101_PMLINK_AOC_OUT 0x3c04
#define GS101_PMLINK_AOC_CTRL 0x3c08
#define GS101_TCXO_BUF_CTRL 0x3c10
#define GS101_ADD_CTRL 0x3c14
#define GS101_HCU_TIMEOUT_RESET 0x3c20
#define GS101_HCU_TIMEOUT_SCAN2DRAM 0x3c24
#define GS101_TIMER(n) (0x3c80 + ((n) & 3) * 4)
#define GS101_PPC_MIF(n) (0x3c90 + ((n) & 3) * 4)
#define GS101_PPC_CORE 0x3ca0
#define GS101_PPC_EH 0x3ca4
#define GS101_PPC_CPUCL1_0 0x3ca8
#define GS101_PPC_CPUCL1_1 0x3cac
#define GS101_EXT_REGULATOR_MIF_DURATION 0x3cb0
#define GS101_EXT_REGULATOR_TOP_DURATION 0x3cb4
#define GS101_EXT_REGULATOR_CPUCL2_DURATION 0x3cb8
#define GS101_EXT_REGULATOR_CPUCL1_DURATION 0x3cbc
#define GS101_EXT_REGULATOR_G3D_DURATION 0x3cc0
#define GS101_EXT_REGULATOR_TPU_DURATION 0x3cc4
#define GS101_TCXO_DURATION 0x3cc8
#define GS101_BURNIN_CTRL 0x3cd0
#define GS101_JTAG_DBG_DET 0x3cd4
#define GS101_MMC_CONWKUP_CTRL 0x3cd8
#define GS101_USBDPPHY0_USBDP_WAKEUP 0x3cdc
#define GS101_TMU_TOP_TRIP 0x3ce0
#define GS101_TMU_SUB_TRIP 0x3ce4
#define GS101_MEMORY_CEN 0x3d00
#define GS101_MEMORY_PGEN 0x3d04
#define GS101_MEMORY_RET 0x3d08
#define GS101_MEMORY_PGEN_FEEDBACK 0x3d0c
#define GS101_MEMORY_SMX 0x3d10
#define GS101_MEMORY_SMX_FEEDBACK 0x3d14
#define GS101_SLC_PCH_CHANNEL 0x3d20
#define GS101_SLC_PCH_CB 0x3d24
#define GS101_FORCE_NOMC 0x3d3c
#define GS101_FORCE_BOOST 0x3d4c
#define GS101_PMLINK_SLC_REQ 0x3d50
#define GS101_PMLINK_SLC_ACK 0x3d54
#define GS101_PMLINK_SLC_BUSY 0x3d58
#define GS101_BOOTSYNC_OUT 0x3d80
#define GS101_BOOTSYNC_IN 0x3d84
#define GS101_SCAN_READY_OUT 0x3d88
#define GS101_SCAN_READY_IN 0x3d8c
#define GS101_GSA_RESTORE 0x3d90
#define GS101_ALIVE_OTP_LATCH 0x3d94
#define GS101_DEBUG_OVERRIDE 0x3d98
#define GS101_WDT_OPTION 0x3d9c
#define GS101_AOC_WDT_CFG 0x3da0
#define GS101_CTRL_SECJTAG_ALIVE 0x3da4
#define GS101_CTRL_DIV_PLL_ALV_DIVLOW 0x3e00
#define GS101_CTRL_MUX_CLK_APM_REFSRC_AUTORESTORE 0x3e04
#define GS101_CTRL_MUX_CLK_APM_REFSRC 0x3e08
#define GS101_CTRL_MUX_CLK_APM_REF 0x3e0c
#define GS101_CTRL_MUX_PLL_ALV_DIV4 0x3e10
#define GS101_CTRL_PLL_ALV_DIV4 0x3e14
#define GS101_CTRL_OSCCLK_APMGSA 0x3e18
#define GS101_CTRL_BLK_AOC_CLKS 0x3e1c
#define GS101_CTRL_PLL_ALV_LOCK 0x3e20
#define GS101_CTRL_CLKDIV__CLKRTC 0x3e24
#define GS101_CTRL_SOC32K 0x3e30
#define GS101_CTRL_STM_PMU 0x3e34
#define GS101_CTRL_PMU_DEBUG 0x3e38
#define GS101_CTRL_DEBUG_UART 0x3e3c
#define GS101_CTRL_TCK 0x3e40
#define GS101_CTRL_SBU_SW_EN 0x3e44
#define GS101_PAD_CTRL_CLKOUT0 0x3e80
#define GS101_PAD_CTRL_CLKOUT1 0x3e84
#define GS101_PAD_CTRL_APM_24MOUT_0 0x3e88
#define GS101_PAD_CTRL_APM_24MOUT_1 0x3e8c
#define GS101_PAD_CTRL_IO_FORCE_RETENTION 0x3e90
#define GS101_PAD_CTRL_APACTIVE_n 0x3e94
#define GS101_PAD_CTRL_TCXO_ON 0x3e98
#define GS101_PAD_CTRL_PWR_HOLD 0x3e9c
#define GS101_PAD_CTRL_RESETO_n 0x3ea0
#define GS101_PAD_CTRL_WRESETO_n 0x3ea4
#define GS101_PHY_CTRL_USB20 0x3eb0
#define GS101_PHY_CTRL_USBDP 0x3eb4
#define GS101_PHY_CTRL_MIPI_DCPHY_M4M4 0x3eb8
#define GS101_PHY_CTRL_MIPI_DCPHY_S4S4S4S4 0x3ebc
#define GS101_PHY_CTRL_PCIE_GEN4_0 0x3ec0
#define GS101_PHY_CTRL_PCIE_GEN4_1 0x3ec4
#define GS101_PHY_CTRL_UFS 0x3ec8
/* PMU INTR GEN */
#define GS101_GRP1_INTR_BID_UPEND (0x0108)