linux/drivers/remoteproc/st_remoteproc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * ST's Remote Processor Control Driver
   4 *
   5 * Copyright (C) 2015 STMicroelectronics - All Rights Reserved
   6 *
   7 * Author: Ludovic Barre <ludovic.barre@st.com>
   8 */
   9
  10#include <linux/clk.h>
  11#include <linux/dma-mapping.h>
  12#include <linux/err.h>
  13#include <linux/interrupt.h>
  14#include <linux/kernel.h>
  15#include <linux/mailbox_client.h>
  16#include <linux/mfd/syscon.h>
  17#include <linux/module.h>
  18#include <linux/of.h>
  19#include <linux/of_address.h>
  20#include <linux/of_device.h>
  21#include <linux/of_reserved_mem.h>
  22#include <linux/platform_device.h>
  23#include <linux/regmap.h>
  24#include <linux/remoteproc.h>
  25#include <linux/reset.h>
  26
  27#include "remoteproc_internal.h"
  28
  29#define ST_RPROC_VQ0            0
  30#define ST_RPROC_VQ1            1
  31#define ST_RPROC_MAX_VRING      2
  32
  33#define MBOX_RX                 0
  34#define MBOX_TX                 1
  35#define MBOX_MAX                2
  36
  37struct st_rproc_config {
  38        bool                    sw_reset;
  39        bool                    pwr_reset;
  40        unsigned long           bootaddr_mask;
  41};
  42
  43struct st_rproc {
  44        struct st_rproc_config  *config;
  45        struct reset_control    *sw_reset;
  46        struct reset_control    *pwr_reset;
  47        struct clk              *clk;
  48        u32                     clk_rate;
  49        struct regmap           *boot_base;
  50        u32                     boot_offset;
  51        struct mbox_chan        *mbox_chan[ST_RPROC_MAX_VRING * MBOX_MAX];
  52        struct mbox_client mbox_client_vq0;
  53        struct mbox_client mbox_client_vq1;
  54};
  55
  56static void st_rproc_mbox_callback(struct device *dev, u32 msg)
  57{
  58        struct rproc *rproc = dev_get_drvdata(dev);
  59
  60        if (rproc_vq_interrupt(rproc, msg) == IRQ_NONE)
  61                dev_dbg(dev, "no message was found in vqid %d\n", msg);
  62}
  63
  64static
  65void st_rproc_mbox_callback_vq0(struct mbox_client *mbox_client, void *data)
  66{
  67        st_rproc_mbox_callback(mbox_client->dev, 0);
  68}
  69
  70static
  71void st_rproc_mbox_callback_vq1(struct mbox_client *mbox_client, void *data)
  72{
  73        st_rproc_mbox_callback(mbox_client->dev, 1);
  74}
  75
  76static void st_rproc_kick(struct rproc *rproc, int vqid)
  77{
  78        struct st_rproc *ddata = rproc->priv;
  79        struct device *dev = rproc->dev.parent;
  80        int ret;
  81
  82        /* send the index of the triggered virtqueue in the mailbox payload */
  83        if (WARN_ON(vqid >= ST_RPROC_MAX_VRING))
  84                return;
  85
  86        ret = mbox_send_message(ddata->mbox_chan[vqid * MBOX_MAX + MBOX_TX],
  87                                (void *)&vqid);
  88        if (ret < 0)
  89                dev_err(dev, "failed to send message via mbox: %d\n", ret);
  90}
  91
  92static int st_rproc_mem_alloc(struct rproc *rproc,
  93                              struct rproc_mem_entry *mem)
  94{
  95        struct device *dev = rproc->dev.parent;
  96        void *va;
  97
  98        va = ioremap_wc(mem->dma, mem->len);
  99        if (!va) {
 100                dev_err(dev, "Unable to map memory region: %pa+%zx\n",
 101                        &mem->dma, mem->len);
 102                return -ENOMEM;
 103        }
 104
 105        /* Update memory entry va */
 106        mem->va = va;
 107
 108        return 0;
 109}
 110
 111static int st_rproc_mem_release(struct rproc *rproc,
 112                                struct rproc_mem_entry *mem)
 113{
 114        iounmap(mem->va);
 115
 116        return 0;
 117}
 118
 119static int st_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw)
 120{
 121        struct device *dev = rproc->dev.parent;
 122        struct device_node *np = dev->of_node;
 123        struct rproc_mem_entry *mem;
 124        struct reserved_mem *rmem;
 125        struct of_phandle_iterator it;
 126        int index = 0;
 127
 128        of_phandle_iterator_init(&it, np, "memory-region", NULL, 0);
 129        while (of_phandle_iterator_next(&it) == 0) {
 130                rmem = of_reserved_mem_lookup(it.node);
 131                if (!rmem) {
 132                        dev_err(dev, "unable to acquire memory-region\n");
 133                        return -EINVAL;
 134                }
 135
 136                /*  No need to map vdev buffer */
 137                if (strcmp(it.node->name, "vdev0buffer")) {
 138                        /* Register memory region */
 139                        mem = rproc_mem_entry_init(dev, NULL,
 140                                                   (dma_addr_t)rmem->base,
 141                                                   rmem->size, rmem->base,
 142                                                   st_rproc_mem_alloc,
 143                                                   st_rproc_mem_release,
 144                                                   it.node->name);
 145                } else {
 146                        /* Register reserved memory for vdev buffer allocation */
 147                        mem = rproc_of_resm_mem_entry_init(dev, index,
 148                                                           rmem->size,
 149                                                           rmem->base,
 150                                                           it.node->name);
 151                }
 152
 153                if (!mem)
 154                        return -ENOMEM;
 155
 156                rproc_add_carveout(rproc, mem);
 157                index++;
 158        }
 159
 160        return rproc_elf_load_rsc_table(rproc, fw);
 161}
 162
 163static int st_rproc_start(struct rproc *rproc)
 164{
 165        struct st_rproc *ddata = rproc->priv;
 166        int err;
 167
 168        regmap_update_bits(ddata->boot_base, ddata->boot_offset,
 169                           ddata->config->bootaddr_mask, rproc->bootaddr);
 170
 171        err = clk_enable(ddata->clk);
 172        if (err) {
 173                dev_err(&rproc->dev, "Failed to enable clock\n");
 174                return err;
 175        }
 176
 177        if (ddata->config->sw_reset) {
 178                err = reset_control_deassert(ddata->sw_reset);
 179                if (err) {
 180                        dev_err(&rproc->dev, "Failed to deassert S/W Reset\n");
 181                        goto sw_reset_fail;
 182                }
 183        }
 184
 185        if (ddata->config->pwr_reset) {
 186                err = reset_control_deassert(ddata->pwr_reset);
 187                if (err) {
 188                        dev_err(&rproc->dev, "Failed to deassert Power Reset\n");
 189                        goto pwr_reset_fail;
 190                }
 191        }
 192
 193        dev_info(&rproc->dev, "Started from 0x%llx\n", rproc->bootaddr);
 194
 195        return 0;
 196
 197
 198pwr_reset_fail:
 199        if (ddata->config->pwr_reset)
 200                reset_control_assert(ddata->sw_reset);
 201sw_reset_fail:
 202        clk_disable(ddata->clk);
 203
 204        return err;
 205}
 206
 207static int st_rproc_stop(struct rproc *rproc)
 208{
 209        struct st_rproc *ddata = rproc->priv;
 210        int sw_err = 0, pwr_err = 0;
 211
 212        if (ddata->config->sw_reset) {
 213                sw_err = reset_control_assert(ddata->sw_reset);
 214                if (sw_err)
 215                        dev_err(&rproc->dev, "Failed to assert S/W Reset\n");
 216        }
 217
 218        if (ddata->config->pwr_reset) {
 219                pwr_err = reset_control_assert(ddata->pwr_reset);
 220                if (pwr_err)
 221                        dev_err(&rproc->dev, "Failed to assert Power Reset\n");
 222        }
 223
 224        clk_disable(ddata->clk);
 225
 226        return sw_err ?: pwr_err;
 227}
 228
 229static const struct rproc_ops st_rproc_ops = {
 230        .kick                   = st_rproc_kick,
 231        .start                  = st_rproc_start,
 232        .stop                   = st_rproc_stop,
 233        .parse_fw               = st_rproc_parse_fw,
 234        .load                   = rproc_elf_load_segments,
 235        .find_loaded_rsc_table  = rproc_elf_find_loaded_rsc_table,
 236        .sanity_check           = rproc_elf_sanity_check,
 237        .get_boot_addr          = rproc_elf_get_boot_addr,
 238};
 239
 240/*
 241 * Fetch state of the processor: 0 is off, 1 is on.
 242 */
 243static int st_rproc_state(struct platform_device *pdev)
 244{
 245        struct rproc *rproc = platform_get_drvdata(pdev);
 246        struct st_rproc *ddata = rproc->priv;
 247        int reset_sw = 0, reset_pwr = 0;
 248
 249        if (ddata->config->sw_reset)
 250                reset_sw = reset_control_status(ddata->sw_reset);
 251
 252        if (ddata->config->pwr_reset)
 253                reset_pwr = reset_control_status(ddata->pwr_reset);
 254
 255        if (reset_sw < 0 || reset_pwr < 0)
 256                return -EINVAL;
 257
 258        return !reset_sw && !reset_pwr;
 259}
 260
 261static const struct st_rproc_config st40_rproc_cfg = {
 262        .sw_reset = true,
 263        .pwr_reset = true,
 264        .bootaddr_mask = GENMASK(28, 1),
 265};
 266
 267static const struct st_rproc_config st231_rproc_cfg = {
 268        .sw_reset = true,
 269        .pwr_reset = false,
 270        .bootaddr_mask = GENMASK(31, 6),
 271};
 272
 273static const struct of_device_id st_rproc_match[] = {
 274        { .compatible = "st,st40-rproc", .data = &st40_rproc_cfg },
 275        { .compatible = "st,st231-rproc", .data = &st231_rproc_cfg },
 276        {},
 277};
 278MODULE_DEVICE_TABLE(of, st_rproc_match);
 279
 280static int st_rproc_parse_dt(struct platform_device *pdev)
 281{
 282        struct device *dev = &pdev->dev;
 283        struct rproc *rproc = platform_get_drvdata(pdev);
 284        struct st_rproc *ddata = rproc->priv;
 285        struct device_node *np = dev->of_node;
 286        int err;
 287
 288        if (ddata->config->sw_reset) {
 289                ddata->sw_reset = devm_reset_control_get_exclusive(dev,
 290                                                                   "sw_reset");
 291                if (IS_ERR(ddata->sw_reset)) {
 292                        dev_err(dev, "Failed to get S/W Reset\n");
 293                        return PTR_ERR(ddata->sw_reset);
 294                }
 295        }
 296
 297        if (ddata->config->pwr_reset) {
 298                ddata->pwr_reset = devm_reset_control_get_exclusive(dev,
 299                                                                    "pwr_reset");
 300                if (IS_ERR(ddata->pwr_reset)) {
 301                        dev_err(dev, "Failed to get Power Reset\n");
 302                        return PTR_ERR(ddata->pwr_reset);
 303                }
 304        }
 305
 306        ddata->clk = devm_clk_get(dev, NULL);
 307        if (IS_ERR(ddata->clk)) {
 308                dev_err(dev, "Failed to get clock\n");
 309                return PTR_ERR(ddata->clk);
 310        }
 311
 312        err = of_property_read_u32(np, "clock-frequency", &ddata->clk_rate);
 313        if (err) {
 314                dev_err(dev, "failed to get clock frequency\n");
 315                return err;
 316        }
 317
 318        ddata->boot_base = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
 319        if (IS_ERR(ddata->boot_base)) {
 320                dev_err(dev, "Boot base not found\n");
 321                return PTR_ERR(ddata->boot_base);
 322        }
 323
 324        err = of_property_read_u32_index(np, "st,syscfg", 1,
 325                                         &ddata->boot_offset);
 326        if (err) {
 327                dev_err(dev, "Boot offset not found\n");
 328                return -EINVAL;
 329        }
 330
 331        err = clk_prepare(ddata->clk);
 332        if (err)
 333                dev_err(dev, "failed to get clock\n");
 334
 335        return err;
 336}
 337
 338static int st_rproc_probe(struct platform_device *pdev)
 339{
 340        struct device *dev = &pdev->dev;
 341        const struct of_device_id *match;
 342        struct st_rproc *ddata;
 343        struct device_node *np = dev->of_node;
 344        struct rproc *rproc;
 345        struct mbox_chan *chan;
 346        int enabled;
 347        int ret, i;
 348
 349        match = of_match_device(st_rproc_match, dev);
 350        if (!match || !match->data) {
 351                dev_err(dev, "No device match found\n");
 352                return -ENODEV;
 353        }
 354
 355        rproc = rproc_alloc(dev, np->name, &st_rproc_ops, NULL, sizeof(*ddata));
 356        if (!rproc)
 357                return -ENOMEM;
 358
 359        rproc->has_iommu = false;
 360        ddata = rproc->priv;
 361        ddata->config = (struct st_rproc_config *)match->data;
 362
 363        platform_set_drvdata(pdev, rproc);
 364
 365        ret = st_rproc_parse_dt(pdev);
 366        if (ret)
 367                goto free_rproc;
 368
 369        enabled = st_rproc_state(pdev);
 370        if (enabled < 0) {
 371                ret = enabled;
 372                goto free_clk;
 373        }
 374
 375        if (enabled) {
 376                atomic_inc(&rproc->power);
 377                rproc->state = RPROC_RUNNING;
 378        } else {
 379                clk_set_rate(ddata->clk, ddata->clk_rate);
 380        }
 381
 382        if (of_get_property(np, "mbox-names", NULL)) {
 383                ddata->mbox_client_vq0.dev              = dev;
 384                ddata->mbox_client_vq0.tx_done          = NULL;
 385                ddata->mbox_client_vq0.tx_block = false;
 386                ddata->mbox_client_vq0.knows_txdone     = false;
 387                ddata->mbox_client_vq0.rx_callback      = st_rproc_mbox_callback_vq0;
 388
 389                ddata->mbox_client_vq1.dev              = dev;
 390                ddata->mbox_client_vq1.tx_done          = NULL;
 391                ddata->mbox_client_vq1.tx_block = false;
 392                ddata->mbox_client_vq1.knows_txdone     = false;
 393                ddata->mbox_client_vq1.rx_callback      = st_rproc_mbox_callback_vq1;
 394
 395                /*
 396                 * To control a co-processor without IPC mechanism.
 397                 * This driver can be used without mbox and rpmsg.
 398                 */
 399                chan = mbox_request_channel_byname(&ddata->mbox_client_vq0, "vq0_rx");
 400                if (IS_ERR(chan)) {
 401                        dev_err(&rproc->dev, "failed to request mbox chan 0\n");
 402                        ret = PTR_ERR(chan);
 403                        goto free_clk;
 404                }
 405                ddata->mbox_chan[ST_RPROC_VQ0 * MBOX_MAX + MBOX_RX] = chan;
 406
 407                chan = mbox_request_channel_byname(&ddata->mbox_client_vq0, "vq0_tx");
 408                if (IS_ERR(chan)) {
 409                        dev_err(&rproc->dev, "failed to request mbox chan 0\n");
 410                        ret = PTR_ERR(chan);
 411                        goto free_mbox;
 412                }
 413                ddata->mbox_chan[ST_RPROC_VQ0 * MBOX_MAX + MBOX_TX] = chan;
 414
 415                chan = mbox_request_channel_byname(&ddata->mbox_client_vq1, "vq1_rx");
 416                if (IS_ERR(chan)) {
 417                        dev_err(&rproc->dev, "failed to request mbox chan 1\n");
 418                        ret = PTR_ERR(chan);
 419                        goto free_mbox;
 420                }
 421                ddata->mbox_chan[ST_RPROC_VQ1 * MBOX_MAX + MBOX_RX] = chan;
 422
 423                chan = mbox_request_channel_byname(&ddata->mbox_client_vq1, "vq1_tx");
 424                if (IS_ERR(chan)) {
 425                        dev_err(&rproc->dev, "failed to request mbox chan 1\n");
 426                        ret = PTR_ERR(chan);
 427                        goto free_mbox;
 428                }
 429                ddata->mbox_chan[ST_RPROC_VQ1 * MBOX_MAX + MBOX_TX] = chan;
 430        }
 431
 432        ret = rproc_add(rproc);
 433        if (ret)
 434                goto free_mbox;
 435
 436        return 0;
 437
 438free_mbox:
 439        for (i = 0; i < ST_RPROC_MAX_VRING * MBOX_MAX; i++)
 440                mbox_free_channel(ddata->mbox_chan[i]);
 441free_clk:
 442        clk_unprepare(ddata->clk);
 443free_rproc:
 444        rproc_free(rproc);
 445        return ret;
 446}
 447
 448static int st_rproc_remove(struct platform_device *pdev)
 449{
 450        struct rproc *rproc = platform_get_drvdata(pdev);
 451        struct st_rproc *ddata = rproc->priv;
 452        int i;
 453
 454        rproc_del(rproc);
 455
 456        clk_disable_unprepare(ddata->clk);
 457
 458        for (i = 0; i < ST_RPROC_MAX_VRING * MBOX_MAX; i++)
 459                mbox_free_channel(ddata->mbox_chan[i]);
 460
 461        rproc_free(rproc);
 462
 463        return 0;
 464}
 465
 466static struct platform_driver st_rproc_driver = {
 467        .probe = st_rproc_probe,
 468        .remove = st_rproc_remove,
 469        .driver = {
 470                .name = "st-rproc",
 471                .of_match_table = of_match_ptr(st_rproc_match),
 472        },
 473};
 474module_platform_driver(st_rproc_driver);
 475
 476MODULE_DESCRIPTION("ST Remote Processor Control Driver");
 477MODULE_AUTHOR("Ludovic Barre <ludovic.barre@st.com>");
 478MODULE_LICENSE("GPL v2");
 479