• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2015
4  * Texas Instruments Incorporated - http://www.ti.com/
5  */
6 #define pr_fmt(fmt) "%s: " fmt, __func__
7 #include <common.h>
8 #include <dm.h>
9 #include <errno.h>
10 #include <remoteproc.h>
11 #include <asm/io.h>
12 
13 /**
14  * enum sandbox_state - different device states
15  * @sb_booted:	Entry condition, just booted
16  * @sb_init:	Initialized (basic environment is ready)
17  * @sb_reset:	Held in reset (accessible, but not running)
18  * @sb_loaded:	Loaded with image (but not running)
19  * @sb_running:	Processor is running
20  */
21 enum sandbox_state {
22 	sb_booted,
23 	sb_init,
24 	sb_reset,
25 	sb_loaded,
26 	sb_running
27 };
28 
29 /**
30  * struct sandbox_test_devdata - private data per device
31  * @current_state:	device current state
32  */
33 struct sandbox_test_devdata {
34 	enum sandbox_state current_state;
35 };
36 
37 /**
38  * sandbox_dev_move_to_state() - statemachine for our dummy device
39  * @dev:	device to switch state
40  * @next_state:	next proposed state
41  *
42  * This tries to follow the following statemachine:
43  *           Entry
44  *            |
45  *            v
46  *         +-------+
47  *     +---+ init  |
48  *     |   |       | <---------------------+
49  *     |   +-------+                       |
50  *     |                                   |
51  *     |                                   |
52  *     |   +--------+                      |
53  * Load|   |  reset |                      |
54  *     |   |        | <----------+         |
55  *     |   +--------+            |         |
56  *     |        |Load            |         |
57  *     |        |                |         |
58  *     |   +----v----+   reset   |         |
59  *     +-> |         |    (opt)  |         |
60  *         |  Loaded +-----------+         |
61  *         |         |                     |
62  *         +----+----+                     |
63  *              | Start                    |
64  *          +---v-----+        (opt)       |
65  *       +->| Running |        Stop        |
66  * Ping  +- |         +--------------------+
67  * (opt)    +---------+
68  *
69  * (is_running does not change state)
70  *
71  * Return: 0 when valid state transition is seen, else returns -EINVAL
72  */
sandbox_dev_move_to_state(struct udevice * dev,enum sandbox_state next_state)73 static int sandbox_dev_move_to_state(struct udevice *dev,
74 				     enum sandbox_state next_state)
75 {
76 	struct sandbox_test_devdata *ddata = dev_get_priv(dev);
77 
78 	/* No state transition is OK */
79 	if (ddata->current_state == next_state)
80 		return 0;
81 
82 	debug("current_state=%d, next_state=%d\n", ddata->current_state,
83 	      next_state);
84 	switch (ddata->current_state) {
85 	case sb_booted:
86 		if (next_state == sb_init)
87 			goto ok_state;
88 		break;
89 
90 	case sb_init:
91 		if (next_state == sb_reset || next_state == sb_loaded)
92 			goto ok_state;
93 		break;
94 
95 	case sb_reset:
96 		if (next_state == sb_loaded || next_state == sb_init)
97 			goto ok_state;
98 		break;
99 
100 	case sb_loaded:
101 		if (next_state == sb_reset || next_state == sb_init ||
102 		    next_state == sb_running)
103 			goto ok_state;
104 		break;
105 
106 	case sb_running:
107 		if (next_state == sb_reset || next_state == sb_init)
108 			goto ok_state;
109 		break;
110 	};
111 	return -EINVAL;
112 
113 ok_state:
114 	ddata->current_state = next_state;
115 	return 0;
116 }
117 
118 /**
119  * sandbox_testproc_probe() - basic probe function
120  * @dev:	test proc device that is being probed.
121  *
122  * Return: 0 if all went ok, else return appropriate error
123  */
sandbox_testproc_probe(struct udevice * dev)124 static int sandbox_testproc_probe(struct udevice *dev)
125 {
126 	struct dm_rproc_uclass_pdata *uc_pdata;
127 	struct sandbox_test_devdata *ddata;
128 	int ret;
129 
130 	uc_pdata = dev_get_uclass_platdata(dev);
131 	ddata = dev_get_priv(dev);
132 	if (!ddata) {
133 		debug("%s: platform private data missing\n", uc_pdata->name);
134 		return -EINVAL;
135 	}
136 	ret = sandbox_dev_move_to_state(dev, sb_booted);
137 	debug("%s: called(%d)\n", uc_pdata->name, ret);
138 
139 	return ret;
140 }
141 
142 /**
143  * sandbox_testproc_init() - Simple initialization function
144  * @dev:	device to operate upon
145  *
146  * Return: 0 if all went ok, else return appropriate error
147  */
sandbox_testproc_init(struct udevice * dev)148 static int sandbox_testproc_init(struct udevice *dev)
149 {
150 	struct dm_rproc_uclass_pdata *uc_pdata;
151 	int ret;
152 
153 	uc_pdata = dev_get_uclass_platdata(dev);
154 
155 	ret = sandbox_dev_move_to_state(dev, sb_init);
156 
157 	debug("%s: called(%d)\n", uc_pdata->name, ret);
158 	if (ret)
159 		debug("%s init failed\n", uc_pdata->name);
160 
161 	return ret;
162 }
163 
164 /**
165  * sandbox_testproc_reset() - Reset the remote processor
166  * @dev:	device to operate upon
167  *
168  * Return: 0 if all went ok, else return appropriate error
169  */
sandbox_testproc_reset(struct udevice * dev)170 static int sandbox_testproc_reset(struct udevice *dev)
171 {
172 	struct dm_rproc_uclass_pdata *uc_pdata;
173 	int ret;
174 
175 	uc_pdata = dev_get_uclass_platdata(dev);
176 
177 	ret = sandbox_dev_move_to_state(dev, sb_reset);
178 
179 	debug("%s: called(%d)\n", uc_pdata->name, ret);
180 
181 	if (ret)
182 		debug("%s reset failed\n", uc_pdata->name);
183 	return ret;
184 }
185 
186 /**
187  * sandbox_testproc_load() - (replace: short desc)
188  * @dev:	device to operate upon
189  * @addr:	Address of the binary image to load
190  * @size:	Size (in bytes) of the binary image to load
191  *
192  * Return: 0 if all went ok, else return appropriate error
193  */
sandbox_testproc_load(struct udevice * dev,ulong addr,ulong size)194 static int sandbox_testproc_load(struct udevice *dev, ulong addr, ulong size)
195 {
196 	struct dm_rproc_uclass_pdata *uc_pdata;
197 	int ret;
198 
199 	uc_pdata = dev_get_uclass_platdata(dev);
200 
201 	ret = sandbox_dev_move_to_state(dev, sb_loaded);
202 
203 	debug("%s: called(%d) Loading to %08lX %lu size\n",
204 	      uc_pdata->name, ret, addr, size);
205 
206 	if (ret)
207 		debug("%s load failed\n", uc_pdata->name);
208 	return ret;
209 }
210 
211 /**
212  * sandbox_testproc_start() - Start the remote processor
213  * @dev:	device to operate upon
214  *
215  * Return: 0 if all went ok, else return appropriate error
216  */
sandbox_testproc_start(struct udevice * dev)217 static int sandbox_testproc_start(struct udevice *dev)
218 {
219 	struct dm_rproc_uclass_pdata *uc_pdata;
220 	int ret;
221 
222 	uc_pdata = dev_get_uclass_platdata(dev);
223 
224 	ret = sandbox_dev_move_to_state(dev, sb_running);
225 
226 	debug("%s: called(%d)\n", uc_pdata->name, ret);
227 
228 	if (ret)
229 		debug("%s start failed\n", uc_pdata->name);
230 	return ret;
231 }
232 
233 /**
234  * sandbox_testproc_stop() - Stop the remote processor
235  * @dev:	device to operate upon
236  *
237  * Return: 0 if all went ok, else return appropriate error
238  */
sandbox_testproc_stop(struct udevice * dev)239 static int sandbox_testproc_stop(struct udevice *dev)
240 {
241 	struct dm_rproc_uclass_pdata *uc_pdata;
242 	int ret;
243 
244 	uc_pdata = dev_get_uclass_platdata(dev);
245 
246 	ret = sandbox_dev_move_to_state(dev, sb_init);
247 
248 	debug("%s: called(%d)\n", uc_pdata->name, ret);
249 
250 	if (ret)
251 		debug("%s stop failed\n", uc_pdata->name);
252 	return ret;
253 }
254 
255 /**
256  * sandbox_testproc_is_running() - Check if remote processor is running
257  * @dev:	device to operate upon
258  *
259  * Return: 0 if running, 1 if not running
260  */
sandbox_testproc_is_running(struct udevice * dev)261 static int sandbox_testproc_is_running(struct udevice *dev)
262 {
263 	struct dm_rproc_uclass_pdata *uc_pdata;
264 	struct sandbox_test_devdata *ddata;
265 	int ret = 1;
266 
267 	uc_pdata = dev_get_uclass_platdata(dev);
268 	ddata = dev_get_priv(dev);
269 
270 	if (ddata->current_state == sb_running)
271 		ret = 0;
272 	debug("%s: called(%d)\n", uc_pdata->name, ret);
273 
274 	return ret;
275 }
276 
277 /**
278  * sandbox_testproc_ping() - Try pinging remote processor
279  * @dev:	device to operate upon
280  *
281  * Return: 0 if running, -EINVAL if not running
282  */
sandbox_testproc_ping(struct udevice * dev)283 static int sandbox_testproc_ping(struct udevice *dev)
284 {
285 	struct dm_rproc_uclass_pdata *uc_pdata;
286 	struct sandbox_test_devdata *ddata;
287 	int ret;
288 
289 	uc_pdata = dev_get_uclass_platdata(dev);
290 	ddata = dev_get_priv(dev);
291 
292 	if (ddata->current_state == sb_running)
293 		ret = 0;
294 	else
295 		ret = -EINVAL;
296 
297 	debug("%s: called(%d)\n", uc_pdata->name, ret);
298 	if (ret)
299 		debug("%s: No response.(Not started?)\n", uc_pdata->name);
300 
301 	return ret;
302 }
303 
304 #define SANDBOX_RPROC_DEV_TO_PHY_OFFSET	0x1000
305 /**
306  * sandbox_testproc_device_to_virt() - Convert device address to virtual address
307  * @dev:	device to operate upon
308  * @da:		device address
309  * @size:	Size of the memory region @da is pointing to
310  * @return converted virtual address
311  */
sandbox_testproc_device_to_virt(struct udevice * dev,ulong da,ulong size)312 static void *sandbox_testproc_device_to_virt(struct udevice *dev, ulong da,
313 					     ulong size)
314 {
315 	u64 paddr;
316 
317 	/* Use a simple offset conversion */
318 	paddr = da + SANDBOX_RPROC_DEV_TO_PHY_OFFSET;
319 
320 	return phys_to_virt(paddr);
321 }
322 
323 static const struct dm_rproc_ops sandbox_testproc_ops = {
324 	.init = sandbox_testproc_init,
325 	.reset = sandbox_testproc_reset,
326 	.load = sandbox_testproc_load,
327 	.start = sandbox_testproc_start,
328 	.stop = sandbox_testproc_stop,
329 	.is_running = sandbox_testproc_is_running,
330 	.ping = sandbox_testproc_ping,
331 	.device_to_virt = sandbox_testproc_device_to_virt,
332 };
333 
334 static const struct udevice_id sandbox_ids[] = {
335 	{.compatible = "sandbox,test-processor"},
336 	{}
337 };
338 
339 U_BOOT_DRIVER(sandbox_testproc) = {
340 	.name = "sandbox_test_proc",
341 	.of_match = sandbox_ids,
342 	.id = UCLASS_REMOTEPROC,
343 	.ops = &sandbox_testproc_ops,
344 	.probe = sandbox_testproc_probe,
345 	.priv_auto_alloc_size = sizeof(struct sandbox_test_devdata),
346 };
347 
348 /* TODO(nm@ti.com): Remove this along with non-DT support */
349 static struct dm_rproc_uclass_pdata proc_3_test = {
350 	.name = "proc_3_legacy",
351 	.mem_type = RPROC_INTERNAL_MEMORY_MAPPED,
352 };
353 
354 U_BOOT_DEVICE(proc_3_demo) = {
355 	.name = "sandbox_test_proc",
356 	.platdata = &proc_3_test,
357 };
358