Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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");