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