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