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