aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2013-04-13 02:06:37 -0400
committerOlof Johansson <olof@lixom.net>2013-04-13 02:14:09 -0400
commitc4c54da24b8ae12abb2034edaf08021894caf0d0 (patch)
tree1b32092803e05b433f124785ae1eb59ca5bd4df2
parent06ff14c05426ec7b7600521c4e1ae19732797e15 (diff)
parent6034bb22d8387708075c083385e5d2e1072a4f33 (diff)
Merge branch 'reset/for_v3.10' of git://git.pengutronix.de/git/pza/linux into next/drivers
From Philipp Zabel, this is a series that adds a simple API for devices to request being reset by a separate reset controller hardware, and it implements reset signal device tree bindings. * 'reset/for_v3.10' of git://git.pengutronix.de/git/pza/linux: reset: NULL deref on allocation failure reset: Add reset controller API dt: describe base reset signal binding Signed-off-by: Olof Johansson <olof@lixom.net>
-rw-r--r--Documentation/devicetree/bindings/reset/reset.txt75
-rw-r--r--drivers/Kconfig2
-rw-r--r--drivers/Makefile3
-rw-r--r--drivers/reset/Kconfig13
-rw-r--r--drivers/reset/Makefile1
-rw-r--r--drivers/reset/core.c297
-rw-r--r--include/linux/reset-controller.h51
-rw-r--r--include/linux/reset.h17
8 files changed, 459 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/reset/reset.txt b/Documentation/devicetree/bindings/reset/reset.txt
new file mode 100644
index 000000000000..31db6ff84908
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/reset.txt
@@ -0,0 +1,75 @@
1= Reset Signal Device Tree Bindings =
2
3This binding is intended to represent the hardware reset signals present
4internally in most IC (SoC, FPGA, ...) designs. Reset signals for whole
5standalone chips are most likely better represented as GPIOs, although there
6are likely to be exceptions to this rule.
7
8Hardware blocks typically receive a reset signal. This signal is generated by
9a reset provider (e.g. power management or clock module) and received by a
10reset consumer (the module being reset, or a module managing when a sub-
11ordinate module is reset). This binding exists to represent the provider and
12consumer, and provide a way to couple the two together.
13
14A reset signal is represented by the phandle of the provider, plus a reset
15specifier - a list of DT cells that represents the reset signal within the
16provider. The length (number of cells) and semantics of the reset specifier
17are dictated by the binding of the reset provider, although common schemes
18are described below.
19
20A word on where to place reset signal consumers in device tree: It is possible
21in hardware for a reset signal to affect multiple logically separate HW blocks
22at once. In this case, it would be unwise to represent this reset signal in
23the DT node of each affected HW block, since if activated, an unrelated block
24may be reset. Instead, reset signals should be represented in the DT node
25where it makes most sense to control it; this may be a bus node if all
26children of the bus are affected by the reset signal, or an individual HW
27block node for dedicated reset signals. The intent of this binding is to give
28appropriate software access to the reset signals in order to manage the HW,
29rather than to slavishly enumerate the reset signal that affects each HW
30block.
31
32= Reset providers =
33
34Required properties:
35#reset-cells: Number of cells in a reset specifier; Typically 0 for nodes
36 with a single reset output and 1 for nodes with multiple
37 reset outputs.
38
39For example:
40
41 rst: reset-controller {
42 #reset-cells = <1>;
43 };
44
45= Reset consumers =
46
47Required properties:
48resets: List of phandle and reset specifier pairs, one pair
49 for each reset signal that affects the device, or that the
50 device manages. Note: if the reset provider specifies '0' for
51 #reset-cells, then only the phandle portion of the pair will
52 appear.
53
54Optional properties:
55reset-names: List of reset signal name strings sorted in the same order as
56 the resets property. Consumers drivers will use reset-names to
57 match reset signal names with reset specifiers.
58
59For example:
60
61 device {
62 resets = <&rst 20>;
63 reset-names = "reset";
64 };
65
66This represents a device with a single reset signal named "reset".
67
68 bus {
69 resets = <&rst 10> <&rst 11> <&rst 12> <&rst 11>;
70 reset-names = "i2s1", "i2s2", "dma", "mixer";
71 };
72
73This represents a bus that controls the reset signal of each of four sub-
74ordinate devices. Consider for example a bus that fails to operate unless no
75child device has reset asserted.
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 202fa6d051b9..847f8e31f3dd 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -162,4 +162,6 @@ source "drivers/irqchip/Kconfig"
162 162
163source "drivers/ipack/Kconfig" 163source "drivers/ipack/Kconfig"
164 164
165source "drivers/reset/Kconfig"
166
165endmenu 167endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index dce39a95fa71..1a64c4cd9094 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -37,6 +37,9 @@ obj-$(CONFIG_XEN) += xen/
37# regulators early, since some subsystems rely on them to initialize 37# regulators early, since some subsystems rely on them to initialize
38obj-$(CONFIG_REGULATOR) += regulator/ 38obj-$(CONFIG_REGULATOR) += regulator/
39 39
40# reset controllers early, since gpu drivers might rely on them to initialize
41obj-$(CONFIG_RESET_CONTROLLER) += reset/
42
40# tty/ comes before char/ so that the VT console is the boot-time 43# tty/ comes before char/ so that the VT console is the boot-time
41# default. 44# default.
42obj-y += tty/ 45obj-y += tty/
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
new file mode 100644
index 000000000000..c9d04f797862
--- /dev/null
+++ b/drivers/reset/Kconfig
@@ -0,0 +1,13 @@
1config ARCH_HAS_RESET_CONTROLLER
2 bool
3
4menuconfig RESET_CONTROLLER
5 bool "Reset Controller Support"
6 default y if ARCH_HAS_RESET_CONTROLLER
7 help
8 Generic Reset Controller support.
9
10 This framework is designed to abstract reset handling of devices
11 via GPIOs or SoC-internal reset controller modules.
12
13 If unsure, say no.
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
new file mode 100644
index 000000000000..1e2d83f2b995
--- /dev/null
+++ b/drivers/reset/Makefile
@@ -0,0 +1 @@
obj-$(CONFIG_RESET_CONTROLLER) += core.o
diff --git a/drivers/reset/core.c b/drivers/reset/core.c
new file mode 100644
index 000000000000..d1b6089a0ef8
--- /dev/null
+++ b/drivers/reset/core.c
@@ -0,0 +1,297 @@
1/*
2 * Reset Controller framework
3 *
4 * Copyright 2013 Philipp Zabel, Pengutronix
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11#include <linux/device.h>
12#include <linux/err.h>
13#include <linux/export.h>
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/of.h>
17#include <linux/reset.h>
18#include <linux/reset-controller.h>
19#include <linux/slab.h>
20
21static DEFINE_MUTEX(reset_controller_list_mutex);
22static LIST_HEAD(reset_controller_list);
23
24/**
25 * struct reset_control - a reset control
26 * @rcdev: a pointer to the reset controller device
27 * this reset control belongs to
28 * @id: ID of the reset controller in the reset
29 * controller device
30 */
31struct reset_control {
32 struct reset_controller_dev *rcdev;
33 struct device *dev;
34 unsigned int id;
35};
36
37/**
38 * of_reset_simple_xlate - translate reset_spec to the reset line number
39 * @rcdev: a pointer to the reset controller device
40 * @reset_spec: reset line specifier as found in the device tree
41 * @flags: a flags pointer to fill in (optional)
42 *
43 * This simple translation function should be used for reset controllers
44 * with 1:1 mapping, where reset lines can be indexed by number without gaps.
45 */
46int of_reset_simple_xlate(struct reset_controller_dev *rcdev,
47 const struct of_phandle_args *reset_spec)
48{
49 if (WARN_ON(reset_spec->args_count != rcdev->of_reset_n_cells))
50 return -EINVAL;
51
52 if (reset_spec->args[0] >= rcdev->nr_resets)
53 return -EINVAL;
54
55 return reset_spec->args[0];
56}
57EXPORT_SYMBOL_GPL(of_reset_simple_xlate);
58
59/**
60 * reset_controller_register - register a reset controller device
61 * @rcdev: a pointer to the initialized reset controller device
62 */
63int reset_controller_register(struct reset_controller_dev *rcdev)
64{
65 if (!rcdev->of_xlate) {
66 rcdev->of_reset_n_cells = 1;
67 rcdev->of_xlate = of_reset_simple_xlate;
68 }
69
70 mutex_lock(&reset_controller_list_mutex);
71 list_add(&rcdev->list, &reset_controller_list);
72 mutex_unlock(&reset_controller_list_mutex);
73
74 return 0;
75}
76EXPORT_SYMBOL_GPL(reset_controller_register);
77
78/**
79 * reset_controller_unregister - unregister a reset controller device
80 * @rcdev: a pointer to the reset controller device
81 */
82void reset_controller_unregister(struct reset_controller_dev *rcdev)
83{
84 mutex_lock(&reset_controller_list_mutex);
85 list_del(&rcdev->list);
86 mutex_unlock(&reset_controller_list_mutex);
87}
88EXPORT_SYMBOL_GPL(reset_controller_unregister);
89
90/**
91 * reset_control_reset - reset the controlled device
92 * @rstc: reset controller
93 */
94int reset_control_reset(struct reset_control *rstc)
95{
96 if (rstc->rcdev->ops->reset)
97 return rstc->rcdev->ops->reset(rstc->rcdev, rstc->id);
98
99 return -ENOSYS;
100}
101EXPORT_SYMBOL_GPL(reset_control_reset);
102
103/**
104 * reset_control_assert - asserts the reset line
105 * @rstc: reset controller
106 */
107int reset_control_assert(struct reset_control *rstc)
108{
109 if (rstc->rcdev->ops->assert)
110 return rstc->rcdev->ops->assert(rstc->rcdev, rstc->id);
111
112 return -ENOSYS;
113}
114EXPORT_SYMBOL_GPL(reset_control_assert);
115
116/**
117 * reset_control_deassert - deasserts the reset line
118 * @rstc: reset controller
119 */
120int reset_control_deassert(struct reset_control *rstc)
121{
122 if (rstc->rcdev->ops->deassert)
123 return rstc->rcdev->ops->deassert(rstc->rcdev, rstc->id);
124
125 return -ENOSYS;
126}
127EXPORT_SYMBOL_GPL(reset_control_deassert);
128
129/**
130 * reset_control_get - Lookup and obtain a reference to a reset controller.
131 * @dev: device to be reset by the controller
132 * @id: reset line name
133 *
134 * Returns a struct reset_control or IS_ERR() condition containing errno.
135 *
136 * Use of id names is optional.
137 */
138struct reset_control *reset_control_get(struct device *dev, const char *id)
139{
140 struct reset_control *rstc = ERR_PTR(-EPROBE_DEFER);
141 struct reset_controller_dev *r, *rcdev;
142 struct of_phandle_args args;
143 int index = 0;
144 int rstc_id;
145 int ret;
146
147 if (!dev)
148 return ERR_PTR(-EINVAL);
149
150 if (id)
151 index = of_property_match_string(dev->of_node,
152 "reset-names", id);
153 ret = of_parse_phandle_with_args(dev->of_node, "resets", "#reset-cells",
154 index, &args);
155 if (ret)
156 return ERR_PTR(ret);
157
158 mutex_lock(&reset_controller_list_mutex);
159 rcdev = NULL;
160 list_for_each_entry(r, &reset_controller_list, list) {
161 if (args.np == r->of_node) {
162 rcdev = r;
163 break;
164 }
165 }
166 of_node_put(args.np);
167
168 if (!rcdev) {
169 mutex_unlock(&reset_controller_list_mutex);
170 return ERR_PTR(-ENODEV);
171 }
172
173 rstc_id = rcdev->of_xlate(rcdev, &args);
174 if (rstc_id < 0) {
175 mutex_unlock(&reset_controller_list_mutex);
176 return ERR_PTR(rstc_id);
177 }
178
179 try_module_get(rcdev->owner);
180 mutex_unlock(&reset_controller_list_mutex);
181
182 rstc = kzalloc(sizeof(*rstc), GFP_KERNEL);
183 if (!rstc) {
184 module_put(rcdev->owner);
185 return ERR_PTR(-ENOMEM);
186 }
187
188 rstc->dev = dev;
189 rstc->rcdev = rcdev;
190 rstc->id = rstc_id;
191
192 return rstc;
193}
194EXPORT_SYMBOL_GPL(reset_control_get);
195
196/**
197 * reset_control_put - free the reset controller
198 * @rstc: reset controller
199 */
200
201void reset_control_put(struct reset_control *rstc)
202{
203 if (IS_ERR(rstc))
204 return;
205
206 module_put(rstc->rcdev->owner);
207 kfree(rstc);
208}
209EXPORT_SYMBOL_GPL(reset_control_put);
210
211static void devm_reset_control_release(struct device *dev, void *res)
212{
213 reset_control_put(*(struct reset_control **)res);
214}
215
216/**
217 * devm_reset_control_get - resource managed reset_control_get()
218 * @dev: device to be reset by the controller
219 * @id: reset line name
220 *
221 * Managed reset_control_get(). For reset controllers returned from this
222 * function, reset_control_put() is called automatically on driver detach.
223 * See reset_control_get() for more information.
224 */
225struct reset_control *devm_reset_control_get(struct device *dev, const char *id)
226{
227 struct reset_control **ptr, *rstc;
228
229 ptr = devres_alloc(devm_reset_control_release, sizeof(*ptr),
230 GFP_KERNEL);
231 if (!ptr)
232 return ERR_PTR(-ENOMEM);
233
234 rstc = reset_control_get(dev, id);
235 if (!IS_ERR(rstc)) {
236 *ptr = rstc;
237 devres_add(dev, ptr);
238 } else {
239 devres_free(ptr);
240 }
241
242 return rstc;
243}
244EXPORT_SYMBOL_GPL(devm_reset_control_get);
245
246static int devm_reset_control_match(struct device *dev, void *res, void *data)
247{
248 struct reset_control **rstc = res;
249 if (WARN_ON(!rstc || !*rstc))
250 return 0;
251 return *rstc == data;
252}
253
254/**
255 * devm_reset_control_put - resource managed reset_control_put()
256 * @rstc: reset controller to free
257 *
258 * Deallocate a reset control allocated withd devm_reset_control_get().
259 * This function will not need to be called normally, as devres will take
260 * care of freeing the resource.
261 */
262void devm_reset_control_put(struct reset_control *rstc)
263{
264 int ret;
265
266 ret = devres_release(rstc->dev, devm_reset_control_release,
267 devm_reset_control_match, rstc);
268 if (ret)
269 WARN_ON(ret);
270}
271EXPORT_SYMBOL_GPL(devm_reset_control_put);
272
273/**
274 * device_reset - find reset controller associated with the device
275 * and perform reset
276 * @dev: device to be reset by the controller
277 *
278 * Convenience wrapper for reset_control_get() and reset_control_reset().
279 * This is useful for the common case of devices with single, dedicated reset
280 * lines.
281 */
282int device_reset(struct device *dev)
283{
284 struct reset_control *rstc;
285 int ret;
286
287 rstc = reset_control_get(dev, NULL);
288 if (IS_ERR(rstc))
289 return PTR_ERR(rstc);
290
291 ret = reset_control_reset(rstc);
292
293 reset_control_put(rstc);
294
295 return ret;
296}
297EXPORT_SYMBOL_GPL(device_reset);
diff --git a/include/linux/reset-controller.h b/include/linux/reset-controller.h
new file mode 100644
index 000000000000..2f61311ae3e0
--- /dev/null
+++ b/include/linux/reset-controller.h
@@ -0,0 +1,51 @@
1#ifndef _LINUX_RESET_CONTROLLER_H_
2#define _LINUX_RESET_CONTROLLER_H_
3
4#include <linux/list.h>
5
6struct reset_controller_dev;
7
8/**
9 * struct reset_control_ops
10 *
11 * @reset: for self-deasserting resets, does all necessary
12 * things to reset the device
13 * @assert: manually assert the reset line, if supported
14 * @deassert: manually deassert the reset line, if supported
15 */
16struct reset_control_ops {
17 int (*reset)(struct reset_controller_dev *rcdev, unsigned long id);
18 int (*assert)(struct reset_controller_dev *rcdev, unsigned long id);
19 int (*deassert)(struct reset_controller_dev *rcdev, unsigned long id);
20};
21
22struct module;
23struct device_node;
24
25/**
26 * struct reset_controller_dev - reset controller entity that might
27 * provide multiple reset controls
28 * @ops: a pointer to device specific struct reset_control_ops
29 * @owner: kernel module of the reset controller driver
30 * @list: internal list of reset controller devices
31 * @of_node: corresponding device tree node as phandle target
32 * @of_reset_n_cells: number of cells in reset line specifiers
33 * @of_xlate: translation function to translate from specifier as found in the
34 * device tree to id as given to the reset control ops
35 * @nr_resets: number of reset controls in this reset controller device
36 */
37struct reset_controller_dev {
38 struct reset_control_ops *ops;
39 struct module *owner;
40 struct list_head list;
41 struct device_node *of_node;
42 int of_reset_n_cells;
43 int (*of_xlate)(struct reset_controller_dev *rcdev,
44 const struct of_phandle_args *reset_spec);
45 unsigned int nr_resets;
46};
47
48int reset_controller_register(struct reset_controller_dev *rcdev);
49void reset_controller_unregister(struct reset_controller_dev *rcdev);
50
51#endif
diff --git a/include/linux/reset.h b/include/linux/reset.h
new file mode 100644
index 000000000000..6082247feab1
--- /dev/null
+++ b/include/linux/reset.h
@@ -0,0 +1,17 @@
1#ifndef _LINUX_RESET_H_
2#define _LINUX_RESET_H_
3
4struct device;
5struct reset_control;
6
7int reset_control_reset(struct reset_control *rstc);
8int reset_control_assert(struct reset_control *rstc);
9int reset_control_deassert(struct reset_control *rstc);
10
11struct reset_control *reset_control_get(struct device *dev, const char *id);
12void reset_control_put(struct reset_control *rstc);
13struct reset_control *devm_reset_control_get(struct device *dev, const char *id);
14
15int device_reset(struct device *dev);
16
17#endif