root/drivers/remoteproc/st_remoteproc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. st_rproc_mbox_callback
  2. st_rproc_mbox_callback_vq0
  3. st_rproc_mbox_callback_vq1
  4. st_rproc_kick
  5. st_rproc_mem_alloc
  6. st_rproc_mem_release
  7. st_rproc_parse_fw
  8. st_rproc_start
  9. st_rproc_stop
  10. st_rproc_state
  11. st_rproc_parse_dt
  12. st_rproc_probe
  13. st_rproc_remove

   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 
  37 struct st_rproc_config {
  38         bool                    sw_reset;
  39         bool                    pwr_reset;
  40         unsigned long           bootaddr_mask;
  41 };
  42 
  43 struct 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 
  56 static 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 
  64 static
  65 void st_rproc_mbox_callback_vq0(struct mbox_client *mbox_client, void *data)
  66 {
  67         st_rproc_mbox_callback(mbox_client->dev, 0);
  68 }
  69 
  70 static
  71 void st_rproc_mbox_callback_vq1(struct mbox_client *mbox_client, void *data)
  72 {
  73         st_rproc_mbox_callback(mbox_client->dev, 1);
  74 }
  75 
  76 static 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 
  92 static 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 
 111 static 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 
 119 static 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 
 163 static 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%x\n", rproc->bootaddr);
 194 
 195         return 0;
 196 
 197 
 198 pwr_reset_fail:
 199         if (ddata->config->pwr_reset)
 200                 reset_control_assert(ddata->sw_reset);
 201 sw_reset_fail:
 202         clk_disable(ddata->clk);
 203 
 204         return err;
 205 }
 206 
 207 static 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 
 229 static 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  */
 243 static 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 
 261 static const struct st_rproc_config st40_rproc_cfg = {
 262         .sw_reset = true,
 263         .pwr_reset = true,
 264         .bootaddr_mask = GENMASK(28, 1),
 265 };
 266 
 267 static const struct st_rproc_config st231_rproc_cfg = {
 268         .sw_reset = true,
 269         .pwr_reset = false,
 270         .bootaddr_mask = GENMASK(31, 6),
 271 };
 272 
 273 static 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 };
 278 MODULE_DEVICE_TABLE(of, st_rproc_match);
 279 
 280 static 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 
 338 static 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 
 438 free_mbox:
 439         for (i = 0; i < ST_RPROC_MAX_VRING * MBOX_MAX; i++)
 440                 mbox_free_channel(ddata->mbox_chan[i]);
 441 free_clk:
 442         clk_unprepare(ddata->clk);
 443 free_rproc:
 444         rproc_free(rproc);
 445         return ret;
 446 }
 447 
 448 static 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 
 466 static 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 };
 474 module_platform_driver(st_rproc_driver);
 475 
 476 MODULE_DESCRIPTION("ST Remote Processor Control Driver");
 477 MODULE_AUTHOR("Ludovic Barre <ludovic.barre@st.com>");
 478 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */