dm: core: Require users of devres to include the header
[oweals/u-boot.git] / drivers / reset / reset-ti-sci.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Texas Instruments System Control Interface (TI SCI) reset driver
4  *
5  * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
6  *      Andreas Dannenberg <dannenberg@ti.com>
7  *
8  * Loosely based on Linux kernel reset-ti-sci.c...
9  */
10
11 #include <common.h>
12 #include <dm.h>
13 #include <errno.h>
14 #include <reset-uclass.h>
15 #include <linux/err.h>
16 #include <linux/soc/ti/ti_sci_protocol.h>
17
18 /**
19  * struct ti_sci_reset_data - reset controller information structure
20  * @sci: TI SCI handle used for communication with system controller
21  */
22 struct ti_sci_reset_data {
23         const struct ti_sci_handle *sci;
24 };
25
26 static int ti_sci_reset_probe(struct udevice *dev)
27 {
28         struct ti_sci_reset_data *data = dev_get_priv(dev);
29
30         debug("%s(dev=%p)\n", __func__, dev);
31
32         if (!data)
33                 return -ENOMEM;
34
35         /* Store handle for communication with the system controller */
36         data->sci = ti_sci_get_handle(dev);
37         if (IS_ERR(data->sci))
38                 return PTR_ERR(data->sci);
39
40         return 0;
41 }
42
43 static int ti_sci_reset_of_xlate(struct reset_ctl *rst,
44                                  struct ofnode_phandle_args *args)
45 {
46         debug("%s(rst=%p, args_count=%d)\n", __func__, rst, args->args_count);
47
48         if (args->args_count != 2) {
49                 debug("Invalid args_count: %d\n", args->args_count);
50                 return -EINVAL;
51         }
52
53         /*
54          * On TI SCI-based devices, the reset provider id field is used as a
55          * device ID, and the data field is used as the associated reset mask.
56          */
57         rst->id = args->args[0];
58         rst->data = args->args[1];
59
60         return 0;
61 }
62
63 static int ti_sci_reset_request(struct reset_ctl *rst)
64 {
65         debug("%s(rst=%p)\n", __func__, rst);
66         return 0;
67 }
68
69 static int ti_sci_reset_free(struct reset_ctl *rst)
70 {
71         debug("%s(rst=%p)\n", __func__, rst);
72         return 0;
73 }
74
75 /**
76  * ti_sci_reset_set() - program a device's reset
77  * @rst: Handle to a single reset signal
78  * @assert: boolean flag to indicate assert or deassert
79  *
80  * This is a common internal function used to assert or deassert a device's
81  * reset using the TI SCI protocol. The device's reset is asserted if the
82  * @assert argument is true, or deasserted if @assert argument is false.
83  * The mechanism itself is a read-modify-write procedure, the current device
84  * reset register is read using a TI SCI device operation, the new value is
85  * set or un-set using the reset's mask, and the new reset value written by
86  * using another TI SCI device operation.
87  *
88  * Return: 0 for successful request, else a corresponding error value
89  */
90 static int ti_sci_reset_set(struct reset_ctl *rst, bool assert)
91 {
92         struct ti_sci_reset_data *data = dev_get_priv(rst->dev);
93         const struct ti_sci_handle *sci = data->sci;
94         const struct ti_sci_dev_ops *dops = &sci->ops.dev_ops;
95         u32 reset_state;
96         int ret;
97
98         ret = dops->get_device_resets(sci, rst->id, &reset_state);
99         if (ret) {
100                 dev_err(rst->dev, "%s: get_device_resets failed (%d)\n",
101                         __func__, ret);
102                 return ret;
103         }
104
105         if (assert)
106                 reset_state |= rst->data;
107         else
108                 reset_state &= ~rst->data;
109
110         ret = dops->set_device_resets(sci, rst->id, reset_state);
111         if (ret) {
112                 dev_err(rst->dev, "%s: set_device_resets failed (%d)\n",
113                         __func__, ret);
114                 return ret;
115         }
116
117         return 0;
118 }
119
120 /**
121  * ti_sci_reset_assert() - assert device reset
122  * @rst: Handle to a single reset signal
123  *
124  * This function implements the reset driver op to assert a device's reset
125  * using the TI SCI protocol. This invokes the function ti_sci_reset_set()
126  * with the corresponding parameters as passed in, but with the @assert
127  * argument set to true for asserting the reset.
128  *
129  * Return: 0 for successful request, else a corresponding error value
130  */
131 static int ti_sci_reset_assert(struct reset_ctl *rst)
132 {
133         debug("%s(rst=%p)\n", __func__, rst);
134         return ti_sci_reset_set(rst, true);
135 }
136
137 /**
138  * ti_sci_reset_deassert() - deassert device reset
139  * @rst: Handle to a single reset signal
140  *
141  * This function implements the reset driver op to deassert a device's reset
142  * using the TI SCI protocol. This invokes the function ti_sci_reset_set()
143  * with the corresponding parameters as passed in, but with the @assert
144  * argument set to false for deasserting the reset.
145  *
146  * Return: 0 for successful request, else a corresponding error value
147  */
148 static int ti_sci_reset_deassert(struct reset_ctl *rst)
149 {
150         debug("%s(rst=%p)\n", __func__, rst);
151         return ti_sci_reset_set(rst, false);
152 }
153
154 /**
155  * ti_sci_reset_status() - check device reset status
156  * @rst: Handle to a single reset signal
157  *
158  * This function implements the reset driver op to return the status of a
159  * device's reset using the TI SCI protocol. The reset register value is read
160  * by invoking the TI SCI device operation .get_device_resets(), and the
161  * status of the specific reset is extracted and returned using this reset's
162  * reset mask.
163  *
164  * Return: 0 if reset is deasserted, or a non-zero value if reset is asserted
165  */
166 static int ti_sci_reset_status(struct reset_ctl *rst)
167 {
168         struct ti_sci_reset_data *data = dev_get_priv(rst->dev);
169         const struct ti_sci_handle *sci = data->sci;
170         const struct ti_sci_dev_ops *dops = &sci->ops.dev_ops;
171         u32 reset_state;
172         int ret;
173
174         debug("%s(rst=%p)\n", __func__, rst);
175
176         ret = dops->get_device_resets(sci, rst->id, &reset_state);
177         if (ret) {
178                 dev_err(rst->dev, "%s: get_device_resets failed (%d)\n",
179                         __func__, ret);
180                 return ret;
181         }
182
183         return reset_state & rst->data;
184 }
185
186 static const struct udevice_id ti_sci_reset_of_match[] = {
187         { .compatible = "ti,sci-reset", },
188         { /* sentinel */ },
189 };
190
191 static struct reset_ops ti_sci_reset_ops = {
192         .of_xlate = ti_sci_reset_of_xlate,
193         .request = ti_sci_reset_request,
194         .rfree = ti_sci_reset_free,
195         .rst_assert = ti_sci_reset_assert,
196         .rst_deassert = ti_sci_reset_deassert,
197         .rst_status = ti_sci_reset_status,
198 };
199
200 U_BOOT_DRIVER(ti_sci_reset) = {
201         .name = "ti-sci-reset",
202         .id = UCLASS_RESET,
203         .of_match = ti_sci_reset_of_match,
204         .probe = ti_sci_reset_probe,
205         .priv_auto_alloc_size = sizeof(struct ti_sci_reset_data),
206         .ops = &ti_sci_reset_ops,
207 };