2019-11-14 12:24:42

by 翟京 (Orson Zhai)

[permalink] [raw]
Subject: [PATCH 0/2] Add syscon name and #cells support


Our SoCs have a lot of glabal registers which is hard to be managed in
current syscon structure.

Same register's offset is different in different SoCs. We used chip
config macro to manage them which prevents driver to be compiled in
all-in-one image.

After talking with Arnd and Rob at Linaro Connect 2017, I got the
idea to extend syscon with #cells support. And furthe, I added syscon
names support to help access multiple syscon nodes more easier.

These patches has been tested in our internal tree about 2 years.

They have no side effect to current syscon consumer.

Thanks,
Orson

--------------------
Orson Zhai (2):
dt-bindings: Add syscon-names support
mfd: syscon: Add syscon-names and phandle args support

.../devicetree/bindings/mfd/syscon.txt | 36 ++++++++++
drivers/mfd/syscon.c | 65 +++++++++++++++++++
include/linux/mfd/syscon.h | 22 +++++++
3 files changed, 123 insertions(+)

--
2.18.0



2019-11-14 12:26:20

by 翟京 (Orson Zhai)

[permalink] [raw]
Subject: [PATCH 2/2] mfd: syscon: Add syscon-names and phandle args support


There are a lot of global registers used across multiple similar SoCs
from Unisoc. It is not easy to manage all of them very well by current
syscon device tree interfaces.

Add helper functions to get regmap and syscon args by syscon-names all
together.

This patch does not affect original syscon code and usage. It may help
other SoC vendors if they have the same trouble as well.

Signed-off-by: Orson Zhai <[email protected]>
---
drivers/mfd/syscon.c | 65 ++++++++++++++++++++++++++++++++++++++
include/linux/mfd/syscon.h | 22 +++++++++++++
2 files changed, 87 insertions(+)

diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
index 660723276481..7ed1b2e4dba4 100644
--- a/drivers/mfd/syscon.c
+++ b/drivers/mfd/syscon.c
@@ -225,6 +225,71 @@ struct regmap *syscon_regmap_lookup_by_phandle(struct device_node *np,
}
EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_phandle);

+struct regmap *syscon_regmap_lookup_by_name(struct device_node *np,
+ const char *name)
+{
+ struct device_node *syscon_np;
+ struct of_phandle_args args;
+ struct regmap *regmap;
+ int index = 0;
+ int rc;
+
+ if (name)
+ index = of_property_match_string(np, "syscon-names", name);
+
+ if (index < 0)
+ return ERR_PTR(-EINVAL);
+
+ rc = of_parse_phandle_with_args(np, "syscons", "#syscon-cells", index,
+ &args);
+ if (rc)
+ return ERR_PTR(rc);
+
+ syscon_np = args.np;
+
+ if (!syscon_np)
+ return ERR_PTR(-ENODEV);
+
+ regmap = syscon_node_to_regmap(syscon_np);
+
+ of_node_put(syscon_np);
+
+ return regmap;
+}
+EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_name);
+
+int syscon_get_args_by_name(struct device_node *np,
+ const char *name,
+ int arg_count,
+ unsigned int *out_args)
+{
+ struct of_phandle_args args;
+ int index = 0;
+ int rc;
+
+ if (name)
+ index = of_property_match_string(np, "syscon-names", name);
+
+ if (index < 0)
+ return -EINVAL;
+
+ rc = of_parse_phandle_with_args(np, "syscons", "#syscon-cells", index,
+ &args);
+ if (rc)
+ return rc;
+
+ if (arg_count > args.args_count)
+ arg_count = args.args_count;
+
+ for (index = 0; index < arg_count; index++)
+ out_args[index] = args.args[index];
+
+ of_node_put(args.np);
+
+ return arg_count;
+}
+EXPORT_SYMBOL_GPL(syscon_get_args_by_name);
+
static int syscon_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
diff --git a/include/linux/mfd/syscon.h b/include/linux/mfd/syscon.h
index 112dc66262cc..5584173cd5d4 100644
--- a/include/linux/mfd/syscon.h
+++ b/include/linux/mfd/syscon.h
@@ -23,6 +23,13 @@ extern struct regmap *syscon_regmap_lookup_by_compatible(const char *s);
extern struct regmap *syscon_regmap_lookup_by_phandle(
struct device_node *np,
const char *property);
+extern struct regmap *syscon_regmap_lookup_by_name(
+ struct device_node *np,
+ const char *name);
+extern int syscon_get_args_by_name(struct device_node *np,
+ const char *name,
+ int arg_count,
+ unsigned int *out_args);
#else
static inline struct regmap *device_node_to_regmap(struct device_node *np)
{
@@ -45,6 +52,21 @@ static inline struct regmap *syscon_regmap_lookup_by_phandle(
{
return ERR_PTR(-ENOTSUPP);
}
+
+static inline struct regmap *syscon_regmap_lookup_by_name(
+ struct device_node *np,
+ const char *name)
+{
+ return ERR_PTR(-ENOTSUPP);
+}
+
+static int syscon_get_args_by_name(struct device_node *np,
+ const char *name,
+ int arg_count,
+ unsigned int *out_args)
+{
+ return -ENOTSUPP;
+}
#endif

#endif /* __LINUX_MFD_SYSCON_H__ */
--
2.18.0