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