hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/mfd/syscon.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * System Control Driver
34 *
....@@ -5,18 +6,13 @@
56 * Copyright (C) 2012 Linaro Ltd.
67 *
78 * Author: Dong Aisheng <dong.aisheng@linaro.org>
8
- *
9
- * This program is free software; you can redistribute it and/or modify
10
- * it under the terms of the GNU General Public License as published by
11
- * the Free Software Foundation; either version 2 of the License, or
12
- * (at your option) any later version.
139 */
1410
1511 #include <linux/clk.h>
1612 #include <linux/err.h>
1713 #include <linux/hwspinlock.h>
1814 #include <linux/io.h>
19
-#include <linux/module.h>
15
+#include <linux/init.h>
2016 #include <linux/list.h>
2117 #include <linux/of.h>
2218 #include <linux/of_address.h>
....@@ -44,7 +40,7 @@
4440 .reg_stride = 4,
4541 };
4642
47
-static struct syscon *of_syscon_register(struct device_node *np)
43
+static struct syscon *of_syscon_register(struct device_node *np, bool check_clk)
4844 {
4945 struct clk *clk;
5046 struct syscon *syscon;
....@@ -54,9 +50,6 @@
5450 int ret;
5551 struct regmap_config syscon_config = syscon_regmap_config;
5652 struct resource res;
57
-
58
- if (!of_device_is_compatible(np, "syscon"))
59
- return ERR_PTR(-EINVAL);
6053
6154 syscon = kzalloc(sizeof(*syscon), GFP_KERNEL);
6255 if (!syscon)
....@@ -102,35 +95,38 @@
10295 break;
10396 default:
10497 pr_err("Failed to retrieve valid hwlock: %d\n", ret);
105
- /* fall-through */
98
+ fallthrough;
10699 case -EPROBE_DEFER:
107100 goto err_regmap;
108101 }
109102 }
110103
111
- syscon_config.name = of_node_full_name(np);
104
+ syscon_config.name = kasprintf(GFP_KERNEL, "%pOFn@%llx", np,
105
+ (u64)res.start);
112106 syscon_config.reg_stride = reg_io_width;
113107 syscon_config.val_bits = reg_io_width * 8;
114108 syscon_config.max_register = resource_size(&res) - reg_io_width;
115
- syscon_config.name = of_node_full_name(np);
116109
117110 regmap = regmap_init_mmio(NULL, base, &syscon_config);
111
+ kfree(syscon_config.name);
118112 if (IS_ERR(regmap)) {
119113 pr_err("regmap init failed\n");
120114 ret = PTR_ERR(regmap);
121115 goto err_regmap;
122116 }
123117
124
- clk = of_clk_get(np, 0);
125
- if (IS_ERR(clk)) {
126
- ret = PTR_ERR(clk);
127
- /* clock is optional */
128
- if (ret != -ENOENT)
129
- goto err_clk;
130
- } else {
131
- ret = regmap_mmio_attach_clk(regmap, clk);
132
- if (ret)
133
- goto err_attach;
118
+ if (check_clk) {
119
+ clk = of_clk_get(np, 0);
120
+ if (IS_ERR(clk)) {
121
+ ret = PTR_ERR(clk);
122
+ /* clock is optional */
123
+ if (ret != -ENOENT)
124
+ goto err_clk;
125
+ } else {
126
+ ret = regmap_mmio_attach_clk(regmap, clk);
127
+ if (ret)
128
+ goto err_attach;
129
+ }
134130 }
135131
136132 syscon->regmap = regmap;
....@@ -154,7 +150,8 @@
154150 return ERR_PTR(ret);
155151 }
156152
157
-struct regmap *syscon_node_to_regmap(struct device_node *np)
153
+static struct regmap *device_node_get_regmap(struct device_node *np,
154
+ bool check_clk)
158155 {
159156 struct syscon *entry, *syscon = NULL;
160157
....@@ -169,12 +166,26 @@
169166 spin_unlock(&syscon_list_slock);
170167
171168 if (!syscon)
172
- syscon = of_syscon_register(np);
169
+ syscon = of_syscon_register(np, check_clk);
173170
174171 if (IS_ERR(syscon))
175172 return ERR_CAST(syscon);
176173
177174 return syscon->regmap;
175
+}
176
+
177
+struct regmap *device_node_to_regmap(struct device_node *np)
178
+{
179
+ return device_node_get_regmap(np, false);
180
+}
181
+EXPORT_SYMBOL_GPL(device_node_to_regmap);
182
+
183
+struct regmap *syscon_node_to_regmap(struct device_node *np)
184
+{
185
+ if (!of_device_is_compatible(np, "syscon"))
186
+ return ERR_PTR(-EINVAL);
187
+
188
+ return device_node_get_regmap(np, true);
178189 }
179190 EXPORT_SYMBOL_GPL(syscon_node_to_regmap);
180191
....@@ -193,27 +204,6 @@
193204 return regmap;
194205 }
195206 EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_compatible);
196
-
197
-static int syscon_match_pdevname(struct device *dev, void *data)
198
-{
199
- return !strcmp(dev_name(dev), (const char *)data);
200
-}
201
-
202
-struct regmap *syscon_regmap_lookup_by_pdevname(const char *s)
203
-{
204
- struct device *dev;
205
- struct syscon *syscon;
206
-
207
- dev = driver_find_device(&syscon_driver.driver, NULL, (void *)s,
208
- syscon_match_pdevname);
209
- if (!dev)
210
- return ERR_PTR(-EPROBE_DEFER);
211
-
212
- syscon = dev_get_drvdata(dev);
213
-
214
- return syscon->regmap;
215
-}
216
-EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_pdevname);
217207
218208 struct regmap *syscon_regmap_lookup_by_phandle(struct device_node *np,
219209 const char *property)
....@@ -236,6 +226,35 @@
236226 }
237227 EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_phandle);
238228
229
+struct regmap *syscon_regmap_lookup_by_phandle_args(struct device_node *np,
230
+ const char *property,
231
+ int arg_count,
232
+ unsigned int *out_args)
233
+{
234
+ struct device_node *syscon_np;
235
+ struct of_phandle_args args;
236
+ struct regmap *regmap;
237
+ unsigned int index;
238
+ int rc;
239
+
240
+ rc = of_parse_phandle_with_fixed_args(np, property, arg_count,
241
+ 0, &args);
242
+ if (rc)
243
+ return ERR_PTR(rc);
244
+
245
+ syscon_np = args.np;
246
+ if (!syscon_np)
247
+ return ERR_PTR(-ENODEV);
248
+
249
+ regmap = syscon_node_to_regmap(syscon_np);
250
+ for (index = 0; index < arg_count; index++)
251
+ out_args[index] = args.args[index];
252
+ of_node_put(syscon_np);
253
+
254
+ return regmap;
255
+}
256
+EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_phandle_args);
257
+
239258 static int syscon_probe(struct platform_device *pdev)
240259 {
241260 struct device *dev = &pdev->dev;
....@@ -257,7 +276,7 @@
257276 if (!base)
258277 return -ENOMEM;
259278
260
- syscon_config.max_register = res->end - res->start - 3;
279
+ syscon_config.max_register = resource_size(res) - 4;
261280 if (pdata)
262281 syscon_config.name = pdata->label;
263282 syscon->regmap = devm_regmap_init_mmio(dev, base, &syscon_config);
....@@ -291,13 +310,3 @@
291310 return platform_driver_register(&syscon_driver);
292311 }
293312 postcore_initcall(syscon_init);
294
-
295
-static void __exit syscon_exit(void)
296
-{
297
- platform_driver_unregister(&syscon_driver);
298
-}
299
-module_exit(syscon_exit);
300
-
301
-MODULE_AUTHOR("Dong Aisheng <dong.aisheng@linaro.org>");
302
-MODULE_DESCRIPTION("System Control driver");
303
-MODULE_LICENSE("GPL v2");