summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Cercueil <paul@crapouillou.net>2019-07-24 13:16:06 -0400
committerPaul Burton <paul.burton@mips.com>2019-08-08 18:30:07 -0400
commit39233b7c611248c0d05209b4854bc63e26485655 (patch)
treedeb77504407a952589c45839385b9b5eaf627d20
parent2e8722a5255e6596246c0feee221902f11178ee5 (diff)
mfd/syscon: Add device_node_to_regmap()
device_node_to_regmap() is exactly like syscon_node_to_regmap(), but it does not check that the node is compatible with "syscon", and won't attach the first clock it finds to the regmap. The rationale behind this, is that one device node with a standard compatible string "foo,bar" can be covered by multiple drivers sharing a regmap, or by a single driver doing all the job without a regmap, but these are implementation details which shouldn't reflect on the devicetree. Signed-off-by: Paul Cercueil <paul@crapouillou.net> Acked-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Paul Burton <paul.burton@mips.com> Cc: Ralf Baechle <ralf@linux-mips.org> Cc: James Hogan <jhogan@kernel.org> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Lee Jones <lee.jones@linaro.org> Cc: Daniel Lezcano <daniel.lezcano@linaro.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Michael Turquette <mturquette@baylibre.com> Cc: Stephen Boyd <sboyd@kernel.org> Cc: Jason Cooper <jason@lakedaemon.net> Cc: Marc Zyngier <marc.zyngier@arm.com> Cc: Rob Herring <robh+dt@kernel.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: devicetree@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: linux-doc@vger.kernel.org Cc: linux-mips@vger.kernel.org Cc: linux-clk@vger.kernel.org Cc: od@zcrc.me Cc: Mathieu Malaterre <malat@debian.org>
-rw-r--r--drivers/mfd/syscon.c46
-rw-r--r--include/linux/mfd/syscon.h6
2 files changed, 36 insertions, 16 deletions
diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
index b65e585fc8c6..660723276481 100644
--- a/drivers/mfd/syscon.c
+++ b/drivers/mfd/syscon.c
@@ -40,7 +40,7 @@ static const struct regmap_config syscon_regmap_config = {
40 .reg_stride = 4, 40 .reg_stride = 4,
41}; 41};
42 42
43static struct syscon *of_syscon_register(struct device_node *np) 43static struct syscon *of_syscon_register(struct device_node *np, bool check_clk)
44{ 44{
45 struct clk *clk; 45 struct clk *clk;
46 struct syscon *syscon; 46 struct syscon *syscon;
@@ -51,9 +51,6 @@ static struct syscon *of_syscon_register(struct device_node *np)
51 struct regmap_config syscon_config = syscon_regmap_config; 51 struct regmap_config syscon_config = syscon_regmap_config;
52 struct resource res; 52 struct resource res;
53 53
54 if (!of_device_is_compatible(np, "syscon"))
55 return ERR_PTR(-EINVAL);
56
57 syscon = kzalloc(sizeof(*syscon), GFP_KERNEL); 54 syscon = kzalloc(sizeof(*syscon), GFP_KERNEL);
58 if (!syscon) 55 if (!syscon)
59 return ERR_PTR(-ENOMEM); 56 return ERR_PTR(-ENOMEM);
@@ -117,16 +114,18 @@ static struct syscon *of_syscon_register(struct device_node *np)
117 goto err_regmap; 114 goto err_regmap;
118 } 115 }
119 116
120 clk = of_clk_get(np, 0); 117 if (check_clk) {
121 if (IS_ERR(clk)) { 118 clk = of_clk_get(np, 0);
122 ret = PTR_ERR(clk); 119 if (IS_ERR(clk)) {
123 /* clock is optional */ 120 ret = PTR_ERR(clk);
124 if (ret != -ENOENT) 121 /* clock is optional */
125 goto err_clk; 122 if (ret != -ENOENT)
126 } else { 123 goto err_clk;
127 ret = regmap_mmio_attach_clk(regmap, clk); 124 } else {
128 if (ret) 125 ret = regmap_mmio_attach_clk(regmap, clk);
129 goto err_attach; 126 if (ret)
127 goto err_attach;
128 }
130 } 129 }
131 130
132 syscon->regmap = regmap; 131 syscon->regmap = regmap;
@@ -150,7 +149,8 @@ err_map:
150 return ERR_PTR(ret); 149 return ERR_PTR(ret);
151} 150}
152 151
153struct regmap *syscon_node_to_regmap(struct device_node *np) 152static struct regmap *device_node_get_regmap(struct device_node *np,
153 bool check_clk)
154{ 154{
155 struct syscon *entry, *syscon = NULL; 155 struct syscon *entry, *syscon = NULL;
156 156
@@ -165,13 +165,27 @@ struct regmap *syscon_node_to_regmap(struct device_node *np)
165 spin_unlock(&syscon_list_slock); 165 spin_unlock(&syscon_list_slock);
166 166
167 if (!syscon) 167 if (!syscon)
168 syscon = of_syscon_register(np); 168 syscon = of_syscon_register(np, check_clk);
169 169
170 if (IS_ERR(syscon)) 170 if (IS_ERR(syscon))
171 return ERR_CAST(syscon); 171 return ERR_CAST(syscon);
172 172
173 return syscon->regmap; 173 return syscon->regmap;
174} 174}
175
176struct regmap *device_node_to_regmap(struct device_node *np)
177{
178 return device_node_get_regmap(np, false);
179}
180EXPORT_SYMBOL_GPL(device_node_to_regmap);
181
182struct regmap *syscon_node_to_regmap(struct device_node *np)
183{
184 if (!of_device_is_compatible(np, "syscon"))
185 return ERR_PTR(-EINVAL);
186
187 return device_node_get_regmap(np, true);
188}
175EXPORT_SYMBOL_GPL(syscon_node_to_regmap); 189EXPORT_SYMBOL_GPL(syscon_node_to_regmap);
176 190
177struct regmap *syscon_regmap_lookup_by_compatible(const char *s) 191struct regmap *syscon_regmap_lookup_by_compatible(const char *s)
diff --git a/include/linux/mfd/syscon.h b/include/linux/mfd/syscon.h
index 8cfda0554381..112dc66262cc 100644
--- a/include/linux/mfd/syscon.h
+++ b/include/linux/mfd/syscon.h
@@ -17,12 +17,18 @@
17struct device_node; 17struct device_node;
18 18
19#ifdef CONFIG_MFD_SYSCON 19#ifdef CONFIG_MFD_SYSCON
20extern struct regmap *device_node_to_regmap(struct device_node *np);
20extern struct regmap *syscon_node_to_regmap(struct device_node *np); 21extern struct regmap *syscon_node_to_regmap(struct device_node *np);
21extern struct regmap *syscon_regmap_lookup_by_compatible(const char *s); 22extern struct regmap *syscon_regmap_lookup_by_compatible(const char *s);
22extern struct regmap *syscon_regmap_lookup_by_phandle( 23extern struct regmap *syscon_regmap_lookup_by_phandle(
23 struct device_node *np, 24 struct device_node *np,
24 const char *property); 25 const char *property);
25#else 26#else
27static inline struct regmap *device_node_to_regmap(struct device_node *np)
28{
29 return ERR_PTR(-ENOTSUPP);
30}
31
26static inline struct regmap *syscon_node_to_regmap(struct device_node *np) 32static inline struct regmap *syscon_node_to_regmap(struct device_node *np)
27{ 33{
28 return ERR_PTR(-ENOTSUPP); 34 return ERR_PTR(-ENOTSUPP);