aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLee Jones <lee@kernel.org>2024-07-04 17:07:34 +0100
committerLee Jones <lee@kernel.org>2024-07-04 17:07:34 +0100
commitf1c6a7e0f07f54718f8cbf9f30ecd2cca9df7334 (patch)
treeafe9e53e162c3cf00fb7352cc05cccb494d466f8
parent2a2ca717cee531788a0e0cbbe71bd0fea5038ff1 (diff)
parent35d6b98c625867209bc47df99cf03edf4280799f (diff)
Merge branch 'ib-mfd-soc-samsung-6.11' into ibs-for-mfd-merged
-rw-r--r--drivers/mfd/syscon.c48
-rw-r--r--drivers/soc/samsung/exynos-pmu.c38
-rw-r--r--include/linux/mfd/syscon.h8
3 files changed, 70 insertions, 24 deletions
diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
index 7d0e91164cba..33f1e07ab24d 100644
--- a/drivers/mfd/syscon.c
+++ b/drivers/mfd/syscon.c
@@ -192,6 +192,54 @@ static struct regmap *device_node_get_regmap(struct device_node *np,
return syscon->regmap;
}
+/**
+ * of_syscon_register_regmap() - Register regmap for specified device node
+ * @np: Device tree node
+ * @regmap: Pointer to regmap object
+ *
+ * Register an externally created regmap object with syscon for the specified
+ * device tree node. This regmap will then be returned to client drivers using
+ * the syscon_regmap_lookup_by_phandle() API.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+int of_syscon_register_regmap(struct device_node *np, struct regmap *regmap)
+{
+ struct syscon *entry, *syscon = NULL;
+ int ret;
+
+ if (!np || !regmap)
+ return -EINVAL;
+
+ syscon = kzalloc(sizeof(*syscon), GFP_KERNEL);
+ if (!syscon)
+ return -ENOMEM;
+
+ /* check if syscon entry already exists */
+ spin_lock(&syscon_list_slock);
+
+ list_for_each_entry(entry, &syscon_list, list)
+ if (entry->np == np) {
+ ret = -EEXIST;
+ goto err_unlock;
+ }
+
+ syscon->regmap = regmap;
+ syscon->np = np;
+
+ /* register the regmap in syscon list */
+ list_add_tail(&syscon->list, &syscon_list);
+ spin_unlock(&syscon_list_slock);
+
+ return 0;
+
+err_unlock:
+ spin_unlock(&syscon_list_slock);
+ kfree(syscon);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(of_syscon_register_regmap);
+
struct regmap *device_node_to_regmap(struct device_node *np)
{
return device_node_get_regmap(np, false);
diff --git a/drivers/soc/samsung/exynos-pmu.c b/drivers/soc/samsung/exynos-pmu.c
index fd8b6ac06656..624324f4001c 100644
--- a/drivers/soc/samsung/exynos-pmu.c
+++ b/drivers/soc/samsung/exynos-pmu.c
@@ -204,16 +204,6 @@ static const struct regmap_config regmap_smccfg = {
.reg_update_bits = tensor_sec_update_bits,
};
-static const struct regmap_config regmap_mmiocfg = {
- .name = "pmu_regs",
- .reg_bits = 32,
- .reg_stride = 4,
- .val_bits = 32,
- .fast_io = true,
- .use_single_read = true,
- .use_single_write = true,
-};
-
static const struct exynos_pmu_data gs101_pmu_data = {
.pmu_secure = true
};
@@ -290,7 +280,6 @@ EXPORT_SYMBOL_GPL(exynos_get_pmu_regmap);
struct regmap *exynos_get_pmu_regmap_by_phandle(struct device_node *np,
const char *propname)
{
- struct exynos_pmu_context *ctx;
struct device_node *pmu_np;
struct device *dev;
@@ -316,9 +305,7 @@ struct regmap *exynos_get_pmu_regmap_by_phandle(struct device_node *np,
if (!dev)
return ERR_PTR(-EPROBE_DEFER);
- ctx = dev_get_drvdata(dev);
-
- return ctx->pmureg;
+ return syscon_node_to_regmap(pmu_np);
}
EXPORT_SYMBOL_GPL(exynos_get_pmu_regmap_by_phandle);
@@ -355,19 +342,22 @@ static int exynos_pmu_probe(struct platform_device *pdev)
regmap = devm_regmap_init(dev, NULL,
(void *)(uintptr_t)res->start,
&pmu_regmcfg);
+
+ if (IS_ERR(regmap))
+ return dev_err_probe(&pdev->dev, PTR_ERR(regmap),
+ "regmap init failed\n");
+
+ ret = of_syscon_register_regmap(dev->of_node, regmap);
+ if (ret)
+ return ret;
} else {
- /* All other SoCs use a MMIO regmap */
- pmu_regmcfg = regmap_mmiocfg;
- pmu_regmcfg.max_register = resource_size(res) -
- pmu_regmcfg.reg_stride;
- regmap = devm_regmap_init_mmio(dev, pmu_base_addr,
- &pmu_regmcfg);
+ /* let syscon create mmio regmap */
+ regmap = syscon_node_to_regmap(dev->of_node);
+ if (IS_ERR(regmap))
+ return dev_err_probe(&pdev->dev, PTR_ERR(regmap),
+ "syscon_node_to_regmap failed\n");
}
- if (IS_ERR(regmap))
- return dev_err_probe(&pdev->dev, PTR_ERR(regmap),
- "regmap init failed\n");
-
pmu_context->pmureg = regmap;
pmu_context->dev = dev;
diff --git a/include/linux/mfd/syscon.h b/include/linux/mfd/syscon.h
index c315903f6dab..aad9c6b50463 100644
--- a/include/linux/mfd/syscon.h
+++ b/include/linux/mfd/syscon.h
@@ -28,6 +28,8 @@ struct regmap *syscon_regmap_lookup_by_phandle_args(struct device_node *np,
unsigned int *out_args);
struct regmap *syscon_regmap_lookup_by_phandle_optional(struct device_node *np,
const char *property);
+int of_syscon_register_regmap(struct device_node *np,
+ struct regmap *regmap);
#else
static inline struct regmap *device_node_to_regmap(struct device_node *np)
{
@@ -67,6 +69,12 @@ static inline struct regmap *syscon_regmap_lookup_by_phandle_optional(
return NULL;
}
+static inline int of_syscon_register_regmap(struct device_node *np,
+ struct regmap *regmap)
+{
+ return -EOPNOTSUPP;
+}
+
#endif
#endif /* __LINUX_MFD_SYSCON_H__ */