summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2025-05-22 00:12:35 +0300
committerArnd Bergmann <arnd@arndb.de>2025-05-22 00:12:36 +0300
commit7148b42e85420bd0d8028a5c5c3611e1c59f6e1f (patch)
treeb4dad049fd962f50765cf395a4db8228de241178
parentf1706e0e1a74b095cbc60375b9b1e6205f5f4c98 (diff)
parent598995027b9181ada81789bf01fb8ef30d93c9dc (diff)
downloadlinux-7148b42e85420bd0d8028a5c5c3611e1c59f6e1f.tar.xz
Merge tag 'samsung-drivers-6.16-2' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux into soc/drivers
Samsung SoC drivers for v6.16, part two Add CPU hotplug support on Google GS101 by toggling respective bits in secondary PMU intr block (Power Management Unit (PMU) Interrupt Generation) from the main PMU driver. * tag 'samsung-drivers-6.16-2' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux: soc: samsung: exynos-pmu: enable CPU hotplug support for gs101 MAINTAINERS: Add google,gs101-pmu-intr-gen.yaml binding file dt-bindings: soc: samsung: exynos-pmu: gs101: add google,pmu-intr-gen phandle dt-bindings: soc: google: Add gs101-pmu-intr-gen binding documentation Link: https://lore.kernel.org/r/20250516082037.7248-2-krzysztof.kozlowski@linaro.org Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r--Documentation/devicetree/bindings/soc/google/google,gs101-pmu-intr-gen.yaml35
-rw-r--r--Documentation/devicetree/bindings/soc/samsung/exynos-pmu.yaml15
-rw-r--r--MAINTAINERS1
-rw-r--r--drivers/soc/samsung/exynos-pmu.c78
-rw-r--r--drivers/soc/samsung/exynos-pmu.h1
-rw-r--r--include/linux/soc/samsung/exynos-regs-pmu.h11
6 files changed, 140 insertions, 1 deletions
diff --git a/Documentation/devicetree/bindings/soc/google/google,gs101-pmu-intr-gen.yaml b/Documentation/devicetree/bindings/soc/google/google,gs101-pmu-intr-gen.yaml
new file mode 100644
index 000000000000..2be022ca6a7d
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/google/google,gs101-pmu-intr-gen.yaml
@@ -0,0 +1,35 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/soc/google/google,gs101-pmu-intr-gen.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Google Power Management Unit (PMU) Interrupt Generation
+
+description: |
+ PMU interrupt generator for handshaking between PMU through interrupts.
+
+maintainers:
+ - Peter Griffin <peter.griffin@linaro.org>
+
+properties:
+ compatible:
+ items:
+ - const: google,gs101-pmu-intr-gen
+ - const: syscon
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ pmu_intr_gen: syscon@17470000 {
+ compatible = "google,gs101-pmu-intr-gen", "syscon";
+ reg = <0x17470000 0x10000>;
+ };
diff --git a/Documentation/devicetree/bindings/soc/samsung/exynos-pmu.yaml b/Documentation/devicetree/bindings/soc/samsung/exynos-pmu.yaml
index 204da6fe458d..3109df43d502 100644
--- a/Documentation/devicetree/bindings/soc/samsung/exynos-pmu.yaml
+++ b/Documentation/devicetree/bindings/soc/samsung/exynos-pmu.yaml
@@ -129,6 +129,11 @@ properties:
description:
Node for reboot method
+ google,pmu-intr-gen-syscon:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ Phandle to PMU interrupt generation interface.
+
required:
- compatible
- reg
@@ -189,6 +194,16 @@ allOf:
properties:
dp-phy: false
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - google,gs101-pmu
+ then:
+ required:
+ - google,pmu-intr-gen-syscon
+
examples:
- |
#include <dt-bindings/clock/exynos5250.h>
diff --git a/MAINTAINERS b/MAINTAINERS
index 8ab070582af9..a2e37782908d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10085,6 +10085,7 @@ L: linux-samsung-soc@vger.kernel.org
S: Maintained
C: irc://irc.oftc.net/pixel6-kernel-dev
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/phy/samsung/phy-gs101-ufs.c
diff --git a/drivers/soc/samsung/exynos-pmu.c b/drivers/soc/samsung/exynos-pmu.c
index c40313886a01..a77288f49d24 100644
--- a/drivers/soc/samsung/exynos-pmu.c
+++ b/drivers/soc/samsung/exynos-pmu.c
@@ -7,6 +7,7 @@
#include <linux/array_size.h>
#include <linux/arm-smccc.h>
+#include <linux/cpuhotplug.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/mfd/core.h>
@@ -33,6 +34,7 @@ struct exynos_pmu_context {
struct device *dev;
const struct exynos_pmu_data *pmu_data;
struct regmap *pmureg;
+ struct regmap *pmuintrgen;
};
void __iomem *pmu_base_addr;
@@ -222,7 +224,8 @@ static const struct regmap_config regmap_smccfg = {
};
static const struct exynos_pmu_data gs101_pmu_data = {
- .pmu_secure = true
+ .pmu_secure = true,
+ .pmu_cpuhp = true,
};
/*
@@ -326,6 +329,59 @@ struct regmap *exynos_get_pmu_regmap_by_phandle(struct device_node *np,
}
EXPORT_SYMBOL_GPL(exynos_get_pmu_regmap_by_phandle);
+/*
+ * CPU_INFORM register hint values which are used by
+ * EL3 firmware (el3mon).
+ */
+#define CPU_INFORM_CLEAR 0
+#define CPU_INFORM_C2 1
+
+static int gs101_cpuhp_pmu_online(unsigned int cpu)
+{
+ unsigned int cpuhint = smp_processor_id();
+ u32 reg, mask;
+
+ /* clear cpu inform hint */
+ regmap_write(pmu_context->pmureg, GS101_CPU_INFORM(cpuhint),
+ CPU_INFORM_CLEAR);
+
+ mask = BIT(cpu);
+
+ regmap_update_bits(pmu_context->pmuintrgen, GS101_GRP2_INTR_BID_ENABLE,
+ mask, (0 << cpu));
+
+ regmap_read(pmu_context->pmuintrgen, GS101_GRP2_INTR_BID_UPEND, &reg);
+
+ regmap_write(pmu_context->pmuintrgen, GS101_GRP2_INTR_BID_CLEAR,
+ reg & mask);
+
+ return 0;
+}
+
+static int gs101_cpuhp_pmu_offline(unsigned int cpu)
+{
+ u32 reg, mask;
+ unsigned int cpuhint = smp_processor_id();
+
+ /* set cpu inform hint */
+ regmap_write(pmu_context->pmureg, GS101_CPU_INFORM(cpuhint),
+ CPU_INFORM_C2);
+
+ mask = BIT(cpu);
+ regmap_update_bits(pmu_context->pmuintrgen, GS101_GRP2_INTR_BID_ENABLE,
+ mask, BIT(cpu));
+
+ regmap_read(pmu_context->pmuintrgen, GS101_GRP1_INTR_BID_UPEND, &reg);
+ regmap_write(pmu_context->pmuintrgen, GS101_GRP1_INTR_BID_CLEAR,
+ reg & mask);
+
+ mask = (BIT(cpu + 8));
+ regmap_read(pmu_context->pmuintrgen, GS101_GRP1_INTR_BID_UPEND, &reg);
+ regmap_write(pmu_context->pmuintrgen, GS101_GRP1_INTR_BID_CLEAR,
+ reg & mask);
+ return 0;
+}
+
static int exynos_pmu_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -378,6 +434,26 @@ static int exynos_pmu_probe(struct platform_device *pdev)
pmu_context->pmureg = regmap;
pmu_context->dev = dev;
+ if (pmu_context->pmu_data && pmu_context->pmu_data->pmu_cpuhp) {
+ pmu_context->pmuintrgen = syscon_regmap_lookup_by_phandle(dev->of_node,
+ "google,pmu-intr-gen-syscon");
+ if (IS_ERR(pmu_context->pmuintrgen)) {
+ /*
+ * To maintain support for older DTs that didn't specify syscon phandle
+ * just issue a warning rather than fail to probe.
+ */
+ dev_warn(&pdev->dev, "pmu-intr-gen syscon unavailable\n");
+ } else {
+ cpuhp_setup_state(CPUHP_BP_PREPARE_DYN,
+ "soc/exynos-pmu:prepare",
+ gs101_cpuhp_pmu_online, NULL);
+
+ cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
+ "soc/exynos-pmu:online",
+ NULL, gs101_cpuhp_pmu_offline);
+ }
+ }
+
if (pmu_context->pmu_data && pmu_context->pmu_data->pmu_init)
pmu_context->pmu_data->pmu_init();
diff --git a/drivers/soc/samsung/exynos-pmu.h b/drivers/soc/samsung/exynos-pmu.h
index 0a49a2c9a08e..0938bb4fe15f 100644
--- a/drivers/soc/samsung/exynos-pmu.h
+++ b/drivers/soc/samsung/exynos-pmu.h
@@ -22,6 +22,7 @@ struct exynos_pmu_data {
const struct exynos_pmu_conf *pmu_config;
const struct exynos_pmu_conf *pmu_config_extra;
bool pmu_secure;
+ bool pmu_cpuhp;
void (*pmu_init)(void);
void (*powerdown_conf)(enum sys_powerdown);
diff --git a/include/linux/soc/samsung/exynos-regs-pmu.h b/include/linux/soc/samsung/exynos-regs-pmu.h
index ce1a3790d6fb..0d5a17ea8fb8 100644
--- a/include/linux/soc/samsung/exynos-regs-pmu.h
+++ b/include/linux/soc/samsung/exynos-regs-pmu.h
@@ -658,9 +658,20 @@
#define EXYNOS5433_PAD_RETENTION_FSYSGENIO_OPTION (0x32A8)
/* 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_PHY_CTRL_USB20 (0x3EB0)
#define GS101_PHY_CTRL_USBDP (0x3EB4)
+/* PMU INTR GEN */
+#define GS101_GRP1_INTR_BID_UPEND (0x0108)
+#define GS101_GRP1_INTR_BID_CLEAR (0x010c)
+#define GS101_GRP2_INTR_BID_ENABLE (0x0200)
+#define GS101_GRP2_INTR_BID_UPEND (0x0208)
+#define GS101_GRP2_INTR_BID_CLEAR (0x020c)
+
#endif /* __LINUX_SOC_EXYNOS_REGS_PMU_H */