cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

imx_rproc.c (23202B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (c) 2017 Pengutronix, Oleksij Rempel <kernel@pengutronix.de>
      4 */
      5
      6#include <linux/arm-smccc.h>
      7#include <linux/clk.h>
      8#include <linux/err.h>
      9#include <linux/interrupt.h>
     10#include <linux/kernel.h>
     11#include <linux/mailbox_client.h>
     12#include <linux/mfd/syscon.h>
     13#include <linux/module.h>
     14#include <linux/of_address.h>
     15#include <linux/of_reserved_mem.h>
     16#include <linux/of_device.h>
     17#include <linux/platform_device.h>
     18#include <linux/regmap.h>
     19#include <linux/remoteproc.h>
     20#include <linux/workqueue.h>
     21
     22#include "imx_rproc.h"
     23#include "remoteproc_internal.h"
     24
     25#define IMX7D_SRC_SCR			0x0C
     26#define IMX7D_ENABLE_M4			BIT(3)
     27#define IMX7D_SW_M4P_RST		BIT(2)
     28#define IMX7D_SW_M4C_RST		BIT(1)
     29#define IMX7D_SW_M4C_NON_SCLR_RST	BIT(0)
     30
     31#define IMX7D_M4_RST_MASK		(IMX7D_ENABLE_M4 | IMX7D_SW_M4P_RST \
     32					 | IMX7D_SW_M4C_RST \
     33					 | IMX7D_SW_M4C_NON_SCLR_RST)
     34
     35#define IMX7D_M4_START			(IMX7D_ENABLE_M4 | IMX7D_SW_M4P_RST \
     36					 | IMX7D_SW_M4C_RST)
     37#define IMX7D_M4_STOP			(IMX7D_ENABLE_M4 | IMX7D_SW_M4C_RST | \
     38					 IMX7D_SW_M4C_NON_SCLR_RST)
     39
     40/* Address: 0x020D8000 */
     41#define IMX6SX_SRC_SCR			0x00
     42#define IMX6SX_ENABLE_M4		BIT(22)
     43#define IMX6SX_SW_M4P_RST		BIT(12)
     44#define IMX6SX_SW_M4C_NON_SCLR_RST	BIT(4)
     45#define IMX6SX_SW_M4C_RST		BIT(3)
     46
     47#define IMX6SX_M4_START			(IMX6SX_ENABLE_M4 | IMX6SX_SW_M4P_RST \
     48					 | IMX6SX_SW_M4C_RST)
     49#define IMX6SX_M4_STOP			(IMX6SX_ENABLE_M4 | IMX6SX_SW_M4C_RST | \
     50					 IMX6SX_SW_M4C_NON_SCLR_RST)
     51#define IMX6SX_M4_RST_MASK		(IMX6SX_ENABLE_M4 | IMX6SX_SW_M4P_RST \
     52					 | IMX6SX_SW_M4C_NON_SCLR_RST \
     53					 | IMX6SX_SW_M4C_RST)
     54
     55#define IMX_RPROC_MEM_MAX		32
     56
     57#define IMX_SIP_RPROC			0xC2000005
     58#define IMX_SIP_RPROC_START		0x00
     59#define IMX_SIP_RPROC_STARTED		0x01
     60#define IMX_SIP_RPROC_STOP		0x02
     61
     62/**
     63 * struct imx_rproc_mem - slim internal memory structure
     64 * @cpu_addr: MPU virtual address of the memory region
     65 * @sys_addr: Bus address used to access the memory region
     66 * @size: Size of the memory region
     67 */
     68struct imx_rproc_mem {
     69	void __iomem *cpu_addr;
     70	phys_addr_t sys_addr;
     71	size_t size;
     72};
     73
     74/* att flags */
     75/* M4 own area. Can be mapped at probe */
     76#define ATT_OWN		BIT(1)
     77#define ATT_IOMEM	BIT(2)
     78
     79struct imx_rproc {
     80	struct device			*dev;
     81	struct regmap			*regmap;
     82	struct rproc			*rproc;
     83	const struct imx_rproc_dcfg	*dcfg;
     84	struct imx_rproc_mem		mem[IMX_RPROC_MEM_MAX];
     85	struct clk			*clk;
     86	struct mbox_client		cl;
     87	struct mbox_chan		*tx_ch;
     88	struct mbox_chan		*rx_ch;
     89	struct work_struct		rproc_work;
     90	struct workqueue_struct		*workqueue;
     91	void __iomem			*rsc_table;
     92};
     93
     94static const struct imx_rproc_att imx_rproc_att_imx93[] = {
     95	/* dev addr , sys addr  , size	    , flags */
     96	/* TCM CODE NON-SECURE */
     97	{ 0x0FFC0000, 0x201C0000, 0x00020000, ATT_OWN | ATT_IOMEM },
     98	{ 0x0FFE0000, 0x201E0000, 0x00020000, ATT_OWN | ATT_IOMEM },
     99
    100	/* TCM CODE SECURE */
    101	{ 0x1FFC0000, 0x201C0000, 0x00020000, ATT_OWN | ATT_IOMEM },
    102	{ 0x1FFE0000, 0x201E0000, 0x00020000, ATT_OWN | ATT_IOMEM },
    103
    104	/* TCM SYS NON-SECURE*/
    105	{ 0x20000000, 0x20200000, 0x00020000, ATT_OWN | ATT_IOMEM },
    106	{ 0x20020000, 0x20220000, 0x00020000, ATT_OWN | ATT_IOMEM },
    107
    108	/* TCM SYS SECURE*/
    109	{ 0x30000000, 0x20200000, 0x00020000, ATT_OWN | ATT_IOMEM },
    110	{ 0x30020000, 0x20220000, 0x00020000, ATT_OWN | ATT_IOMEM },
    111
    112	/* DDR */
    113	{ 0x80000000, 0x80000000, 0x10000000, 0 },
    114	{ 0x90000000, 0x80000000, 0x10000000, 0 },
    115
    116	{ 0xC0000000, 0xa0000000, 0x10000000, 0 },
    117	{ 0xD0000000, 0xa0000000, 0x10000000, 0 },
    118};
    119
    120static const struct imx_rproc_att imx_rproc_att_imx8mn[] = {
    121	/* dev addr , sys addr  , size	    , flags */
    122	/* ITCM   */
    123	{ 0x00000000, 0x007E0000, 0x00020000, ATT_OWN | ATT_IOMEM },
    124	/* OCRAM_S */
    125	{ 0x00180000, 0x00180000, 0x00009000, 0 },
    126	/* OCRAM */
    127	{ 0x00900000, 0x00900000, 0x00020000, 0 },
    128	/* OCRAM */
    129	{ 0x00920000, 0x00920000, 0x00020000, 0 },
    130	/* OCRAM */
    131	{ 0x00940000, 0x00940000, 0x00050000, 0 },
    132	/* QSPI Code - alias */
    133	{ 0x08000000, 0x08000000, 0x08000000, 0 },
    134	/* DDR (Code) - alias */
    135	{ 0x10000000, 0x40000000, 0x0FFE0000, 0 },
    136	/* DTCM */
    137	{ 0x20000000, 0x00800000, 0x00020000, ATT_OWN | ATT_IOMEM },
    138	/* OCRAM_S - alias */
    139	{ 0x20180000, 0x00180000, 0x00008000, ATT_OWN },
    140	/* OCRAM */
    141	{ 0x20200000, 0x00900000, 0x00020000, ATT_OWN },
    142	/* OCRAM */
    143	{ 0x20220000, 0x00920000, 0x00020000, ATT_OWN },
    144	/* OCRAM */
    145	{ 0x20240000, 0x00940000, 0x00040000, ATT_OWN },
    146	/* DDR (Data) */
    147	{ 0x40000000, 0x40000000, 0x80000000, 0 },
    148};
    149
    150static const struct imx_rproc_att imx_rproc_att_imx8mq[] = {
    151	/* dev addr , sys addr  , size	    , flags */
    152	/* TCML - alias */
    153	{ 0x00000000, 0x007e0000, 0x00020000, ATT_IOMEM},
    154	/* OCRAM_S */
    155	{ 0x00180000, 0x00180000, 0x00008000, 0 },
    156	/* OCRAM */
    157	{ 0x00900000, 0x00900000, 0x00020000, 0 },
    158	/* OCRAM */
    159	{ 0x00920000, 0x00920000, 0x00020000, 0 },
    160	/* QSPI Code - alias */
    161	{ 0x08000000, 0x08000000, 0x08000000, 0 },
    162	/* DDR (Code) - alias */
    163	{ 0x10000000, 0x80000000, 0x0FFE0000, 0 },
    164	/* TCML */
    165	{ 0x1FFE0000, 0x007E0000, 0x00020000, ATT_OWN  | ATT_IOMEM},
    166	/* TCMU */
    167	{ 0x20000000, 0x00800000, 0x00020000, ATT_OWN  | ATT_IOMEM},
    168	/* OCRAM_S */
    169	{ 0x20180000, 0x00180000, 0x00008000, ATT_OWN },
    170	/* OCRAM */
    171	{ 0x20200000, 0x00900000, 0x00020000, ATT_OWN },
    172	/* OCRAM */
    173	{ 0x20220000, 0x00920000, 0x00020000, ATT_OWN },
    174	/* DDR (Data) */
    175	{ 0x40000000, 0x40000000, 0x80000000, 0 },
    176};
    177
    178static const struct imx_rproc_att imx_rproc_att_imx8ulp[] = {
    179	{0x1FFC0000, 0x1FFC0000, 0xC0000, ATT_OWN},
    180	{0x21000000, 0x21000000, 0x10000, ATT_OWN},
    181	{0x80000000, 0x80000000, 0x60000000, 0}
    182};
    183
    184static const struct imx_rproc_att imx_rproc_att_imx7ulp[] = {
    185	{0x1FFD0000, 0x1FFD0000, 0x30000, ATT_OWN},
    186	{0x20000000, 0x20000000, 0x10000, ATT_OWN},
    187	{0x2F000000, 0x2F000000, 0x20000, ATT_OWN},
    188	{0x2F020000, 0x2F020000, 0x20000, ATT_OWN},
    189	{0x60000000, 0x60000000, 0x40000000, 0}
    190};
    191
    192static const struct imx_rproc_att imx_rproc_att_imx7d[] = {
    193	/* dev addr , sys addr  , size	    , flags */
    194	/* OCRAM_S (M4 Boot code) - alias */
    195	{ 0x00000000, 0x00180000, 0x00008000, 0 },
    196	/* OCRAM_S (Code) */
    197	{ 0x00180000, 0x00180000, 0x00008000, ATT_OWN },
    198	/* OCRAM (Code) - alias */
    199	{ 0x00900000, 0x00900000, 0x00020000, 0 },
    200	/* OCRAM_EPDC (Code) - alias */
    201	{ 0x00920000, 0x00920000, 0x00020000, 0 },
    202	/* OCRAM_PXP (Code) - alias */
    203	{ 0x00940000, 0x00940000, 0x00008000, 0 },
    204	/* TCML (Code) */
    205	{ 0x1FFF8000, 0x007F8000, 0x00008000, ATT_OWN | ATT_IOMEM },
    206	/* DDR (Code) - alias, first part of DDR (Data) */
    207	{ 0x10000000, 0x80000000, 0x0FFF0000, 0 },
    208
    209	/* TCMU (Data) */
    210	{ 0x20000000, 0x00800000, 0x00008000, ATT_OWN | ATT_IOMEM },
    211	/* OCRAM (Data) */
    212	{ 0x20200000, 0x00900000, 0x00020000, 0 },
    213	/* OCRAM_EPDC (Data) */
    214	{ 0x20220000, 0x00920000, 0x00020000, 0 },
    215	/* OCRAM_PXP (Data) */
    216	{ 0x20240000, 0x00940000, 0x00008000, 0 },
    217	/* DDR (Data) */
    218	{ 0x80000000, 0x80000000, 0x60000000, 0 },
    219};
    220
    221static const struct imx_rproc_att imx_rproc_att_imx6sx[] = {
    222	/* dev addr , sys addr  , size	    , flags */
    223	/* TCML (M4 Boot Code) - alias */
    224	{ 0x00000000, 0x007F8000, 0x00008000, ATT_IOMEM },
    225	/* OCRAM_S (Code) */
    226	{ 0x00180000, 0x008F8000, 0x00004000, 0 },
    227	/* OCRAM_S (Code) - alias */
    228	{ 0x00180000, 0x008FC000, 0x00004000, 0 },
    229	/* TCML (Code) */
    230	{ 0x1FFF8000, 0x007F8000, 0x00008000, ATT_OWN | ATT_IOMEM },
    231	/* DDR (Code) - alias, first part of DDR (Data) */
    232	{ 0x10000000, 0x80000000, 0x0FFF8000, 0 },
    233
    234	/* TCMU (Data) */
    235	{ 0x20000000, 0x00800000, 0x00008000, ATT_OWN | ATT_IOMEM },
    236	/* OCRAM_S (Data) - alias? */
    237	{ 0x208F8000, 0x008F8000, 0x00004000, 0 },
    238	/* DDR (Data) */
    239	{ 0x80000000, 0x80000000, 0x60000000, 0 },
    240};
    241
    242static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mn = {
    243	.att		= imx_rproc_att_imx8mn,
    244	.att_size	= ARRAY_SIZE(imx_rproc_att_imx8mn),
    245	.method		= IMX_RPROC_SMC,
    246};
    247
    248static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mq = {
    249	.src_reg	= IMX7D_SRC_SCR,
    250	.src_mask	= IMX7D_M4_RST_MASK,
    251	.src_start	= IMX7D_M4_START,
    252	.src_stop	= IMX7D_M4_STOP,
    253	.att		= imx_rproc_att_imx8mq,
    254	.att_size	= ARRAY_SIZE(imx_rproc_att_imx8mq),
    255	.method		= IMX_RPROC_MMIO,
    256};
    257
    258static const struct imx_rproc_dcfg imx_rproc_cfg_imx8ulp = {
    259	.att		= imx_rproc_att_imx8ulp,
    260	.att_size	= ARRAY_SIZE(imx_rproc_att_imx8ulp),
    261	.method		= IMX_RPROC_NONE,
    262};
    263
    264static const struct imx_rproc_dcfg imx_rproc_cfg_imx7ulp = {
    265	.att		= imx_rproc_att_imx7ulp,
    266	.att_size	= ARRAY_SIZE(imx_rproc_att_imx7ulp),
    267	.method		= IMX_RPROC_NONE,
    268};
    269
    270static const struct imx_rproc_dcfg imx_rproc_cfg_imx7d = {
    271	.src_reg	= IMX7D_SRC_SCR,
    272	.src_mask	= IMX7D_M4_RST_MASK,
    273	.src_start	= IMX7D_M4_START,
    274	.src_stop	= IMX7D_M4_STOP,
    275	.att		= imx_rproc_att_imx7d,
    276	.att_size	= ARRAY_SIZE(imx_rproc_att_imx7d),
    277	.method		= IMX_RPROC_MMIO,
    278};
    279
    280static const struct imx_rproc_dcfg imx_rproc_cfg_imx6sx = {
    281	.src_reg	= IMX6SX_SRC_SCR,
    282	.src_mask	= IMX6SX_M4_RST_MASK,
    283	.src_start	= IMX6SX_M4_START,
    284	.src_stop	= IMX6SX_M4_STOP,
    285	.att		= imx_rproc_att_imx6sx,
    286	.att_size	= ARRAY_SIZE(imx_rproc_att_imx6sx),
    287	.method		= IMX_RPROC_MMIO,
    288};
    289
    290static const struct imx_rproc_dcfg imx_rproc_cfg_imx93 = {
    291	.att		= imx_rproc_att_imx93,
    292	.att_size	= ARRAY_SIZE(imx_rproc_att_imx93),
    293	.method		= IMX_RPROC_SMC,
    294};
    295
    296static int imx_rproc_start(struct rproc *rproc)
    297{
    298	struct imx_rproc *priv = rproc->priv;
    299	const struct imx_rproc_dcfg *dcfg = priv->dcfg;
    300	struct device *dev = priv->dev;
    301	struct arm_smccc_res res;
    302	int ret;
    303
    304	switch (dcfg->method) {
    305	case IMX_RPROC_MMIO:
    306		ret = regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask,
    307					 dcfg->src_start);
    308		break;
    309	case IMX_RPROC_SMC:
    310		arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_START, 0, 0, 0, 0, 0, 0, &res);
    311		ret = res.a0;
    312		break;
    313	default:
    314		return -EOPNOTSUPP;
    315	}
    316
    317	if (ret)
    318		dev_err(dev, "Failed to enable remote core!\n");
    319
    320	return ret;
    321}
    322
    323static int imx_rproc_stop(struct rproc *rproc)
    324{
    325	struct imx_rproc *priv = rproc->priv;
    326	const struct imx_rproc_dcfg *dcfg = priv->dcfg;
    327	struct device *dev = priv->dev;
    328	struct arm_smccc_res res;
    329	int ret;
    330
    331	switch (dcfg->method) {
    332	case IMX_RPROC_MMIO:
    333		ret = regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask,
    334					 dcfg->src_stop);
    335		break;
    336	case IMX_RPROC_SMC:
    337		arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_STOP, 0, 0, 0, 0, 0, 0, &res);
    338		ret = res.a0;
    339		if (res.a1)
    340			dev_info(dev, "Not in wfi, force stopped\n");
    341		break;
    342	default:
    343		return -EOPNOTSUPP;
    344	}
    345
    346	if (ret)
    347		dev_err(dev, "Failed to stop remote core\n");
    348
    349	return ret;
    350}
    351
    352static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da,
    353			       size_t len, u64 *sys, bool *is_iomem)
    354{
    355	const struct imx_rproc_dcfg *dcfg = priv->dcfg;
    356	int i;
    357
    358	/* parse address translation table */
    359	for (i = 0; i < dcfg->att_size; i++) {
    360		const struct imx_rproc_att *att = &dcfg->att[i];
    361
    362		if (da >= att->da && da + len < att->da + att->size) {
    363			unsigned int offset = da - att->da;
    364
    365			*sys = att->sa + offset;
    366			if (is_iomem)
    367				*is_iomem = att->flags & ATT_IOMEM;
    368			return 0;
    369		}
    370	}
    371
    372	dev_warn(priv->dev, "Translation failed: da = 0x%llx len = 0x%zx\n",
    373		 da, len);
    374	return -ENOENT;
    375}
    376
    377static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
    378{
    379	struct imx_rproc *priv = rproc->priv;
    380	void *va = NULL;
    381	u64 sys;
    382	int i;
    383
    384	if (len == 0)
    385		return NULL;
    386
    387	/*
    388	 * On device side we have many aliases, so we need to convert device
    389	 * address (M4) to system bus address first.
    390	 */
    391	if (imx_rproc_da_to_sys(priv, da, len, &sys, is_iomem))
    392		return NULL;
    393
    394	for (i = 0; i < IMX_RPROC_MEM_MAX; i++) {
    395		if (sys >= priv->mem[i].sys_addr && sys + len <
    396		    priv->mem[i].sys_addr +  priv->mem[i].size) {
    397			unsigned int offset = sys - priv->mem[i].sys_addr;
    398			/* __force to make sparse happy with type conversion */
    399			va = (__force void *)(priv->mem[i].cpu_addr + offset);
    400			break;
    401		}
    402	}
    403
    404	dev_dbg(&rproc->dev, "da = 0x%llx len = 0x%zx va = 0x%p\n",
    405		da, len, va);
    406
    407	return va;
    408}
    409
    410static int imx_rproc_mem_alloc(struct rproc *rproc,
    411			       struct rproc_mem_entry *mem)
    412{
    413	struct device *dev = rproc->dev.parent;
    414	void *va;
    415
    416	dev_dbg(dev, "map memory: %p+%zx\n", &mem->dma, mem->len);
    417	va = ioremap_wc(mem->dma, mem->len);
    418	if (IS_ERR_OR_NULL(va)) {
    419		dev_err(dev, "Unable to map memory region: %p+%zx\n",
    420			&mem->dma, mem->len);
    421		return -ENOMEM;
    422	}
    423
    424	/* Update memory entry va */
    425	mem->va = va;
    426
    427	return 0;
    428}
    429
    430static int imx_rproc_mem_release(struct rproc *rproc,
    431				 struct rproc_mem_entry *mem)
    432{
    433	dev_dbg(rproc->dev.parent, "unmap memory: %pa\n", &mem->dma);
    434	iounmap(mem->va);
    435
    436	return 0;
    437}
    438
    439static int imx_rproc_prepare(struct rproc *rproc)
    440{
    441	struct imx_rproc *priv = rproc->priv;
    442	struct device_node *np = priv->dev->of_node;
    443	struct of_phandle_iterator it;
    444	struct rproc_mem_entry *mem;
    445	struct reserved_mem *rmem;
    446	u32 da;
    447
    448	/* Register associated reserved memory regions */
    449	of_phandle_iterator_init(&it, np, "memory-region", NULL, 0);
    450	while (of_phandle_iterator_next(&it) == 0) {
    451		/*
    452		 * Ignore the first memory region which will be used vdev buffer.
    453		 * No need to do extra handlings, rproc_add_virtio_dev will handle it.
    454		 */
    455		if (!strcmp(it.node->name, "vdev0buffer"))
    456			continue;
    457
    458		if (!strcmp(it.node->name, "rsc-table"))
    459			continue;
    460
    461		rmem = of_reserved_mem_lookup(it.node);
    462		if (!rmem) {
    463			dev_err(priv->dev, "unable to acquire memory-region\n");
    464			return -EINVAL;
    465		}
    466
    467		/* No need to translate pa to da, i.MX use same map */
    468		da = rmem->base;
    469
    470		/* Register memory region */
    471		mem = rproc_mem_entry_init(priv->dev, NULL, (dma_addr_t)rmem->base, rmem->size, da,
    472					   imx_rproc_mem_alloc, imx_rproc_mem_release,
    473					   it.node->name);
    474
    475		if (mem)
    476			rproc_coredump_add_segment(rproc, da, rmem->size);
    477		else
    478			return -ENOMEM;
    479
    480		rproc_add_carveout(rproc, mem);
    481	}
    482
    483	return  0;
    484}
    485
    486static int imx_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw)
    487{
    488	int ret;
    489
    490	ret = rproc_elf_load_rsc_table(rproc, fw);
    491	if (ret)
    492		dev_info(&rproc->dev, "No resource table in elf\n");
    493
    494	return 0;
    495}
    496
    497static void imx_rproc_kick(struct rproc *rproc, int vqid)
    498{
    499	struct imx_rproc *priv = rproc->priv;
    500	int err;
    501	__u32 mmsg;
    502
    503	if (!priv->tx_ch) {
    504		dev_err(priv->dev, "No initialized mbox tx channel\n");
    505		return;
    506	}
    507
    508	/*
    509	 * Send the index of the triggered virtqueue as the mu payload.
    510	 * Let remote processor know which virtqueue is used.
    511	 */
    512	mmsg = vqid << 16;
    513
    514	err = mbox_send_message(priv->tx_ch, (void *)&mmsg);
    515	if (err < 0)
    516		dev_err(priv->dev, "%s: failed (%d, err:%d)\n",
    517			__func__, vqid, err);
    518}
    519
    520static int imx_rproc_attach(struct rproc *rproc)
    521{
    522	return 0;
    523}
    524
    525static struct resource_table *imx_rproc_get_loaded_rsc_table(struct rproc *rproc, size_t *table_sz)
    526{
    527	struct imx_rproc *priv = rproc->priv;
    528
    529	/* The resource table has already been mapped in imx_rproc_addr_init */
    530	if (!priv->rsc_table)
    531		return NULL;
    532
    533	*table_sz = SZ_1K;
    534	return (struct resource_table *)priv->rsc_table;
    535}
    536
    537static const struct rproc_ops imx_rproc_ops = {
    538	.prepare	= imx_rproc_prepare,
    539	.attach		= imx_rproc_attach,
    540	.start		= imx_rproc_start,
    541	.stop		= imx_rproc_stop,
    542	.kick		= imx_rproc_kick,
    543	.da_to_va       = imx_rproc_da_to_va,
    544	.load		= rproc_elf_load_segments,
    545	.parse_fw	= imx_rproc_parse_fw,
    546	.find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table,
    547	.get_loaded_rsc_table = imx_rproc_get_loaded_rsc_table,
    548	.sanity_check	= rproc_elf_sanity_check,
    549	.get_boot_addr	= rproc_elf_get_boot_addr,
    550};
    551
    552static int imx_rproc_addr_init(struct imx_rproc *priv,
    553			       struct platform_device *pdev)
    554{
    555	const struct imx_rproc_dcfg *dcfg = priv->dcfg;
    556	struct device *dev = &pdev->dev;
    557	struct device_node *np = dev->of_node;
    558	int a, b = 0, err, nph;
    559
    560	/* remap required addresses */
    561	for (a = 0; a < dcfg->att_size; a++) {
    562		const struct imx_rproc_att *att = &dcfg->att[a];
    563
    564		if (!(att->flags & ATT_OWN))
    565			continue;
    566
    567		if (b >= IMX_RPROC_MEM_MAX)
    568			break;
    569
    570		if (att->flags & ATT_IOMEM)
    571			priv->mem[b].cpu_addr = devm_ioremap(&pdev->dev,
    572							     att->sa, att->size);
    573		else
    574			priv->mem[b].cpu_addr = devm_ioremap_wc(&pdev->dev,
    575								att->sa, att->size);
    576		if (!priv->mem[b].cpu_addr) {
    577			dev_err(dev, "failed to remap %#x bytes from %#x\n", att->size, att->sa);
    578			return -ENOMEM;
    579		}
    580		priv->mem[b].sys_addr = att->sa;
    581		priv->mem[b].size = att->size;
    582		b++;
    583	}
    584
    585	/* memory-region is optional property */
    586	nph = of_count_phandle_with_args(np, "memory-region", NULL);
    587	if (nph <= 0)
    588		return 0;
    589
    590	/* remap optional addresses */
    591	for (a = 0; a < nph; a++) {
    592		struct device_node *node;
    593		struct resource res;
    594
    595		node = of_parse_phandle(np, "memory-region", a);
    596		/* Not map vdevbuffer, vdevring region */
    597		if (!strncmp(node->name, "vdev", strlen("vdev")))
    598			continue;
    599		err = of_address_to_resource(node, 0, &res);
    600		if (err) {
    601			dev_err(dev, "unable to resolve memory region\n");
    602			return err;
    603		}
    604
    605		of_node_put(node);
    606
    607		if (b >= IMX_RPROC_MEM_MAX)
    608			break;
    609
    610		/* Not use resource version, because we might share region */
    611		priv->mem[b].cpu_addr = devm_ioremap_wc(&pdev->dev, res.start, resource_size(&res));
    612		if (!priv->mem[b].cpu_addr) {
    613			dev_err(dev, "failed to remap %pr\n", &res);
    614			return -ENOMEM;
    615		}
    616		priv->mem[b].sys_addr = res.start;
    617		priv->mem[b].size = resource_size(&res);
    618		if (!strcmp(node->name, "rsc-table"))
    619			priv->rsc_table = priv->mem[b].cpu_addr;
    620		b++;
    621	}
    622
    623	return 0;
    624}
    625
    626static void imx_rproc_vq_work(struct work_struct *work)
    627{
    628	struct imx_rproc *priv = container_of(work, struct imx_rproc,
    629					      rproc_work);
    630
    631	rproc_vq_interrupt(priv->rproc, 0);
    632	rproc_vq_interrupt(priv->rproc, 1);
    633}
    634
    635static void imx_rproc_rx_callback(struct mbox_client *cl, void *msg)
    636{
    637	struct rproc *rproc = dev_get_drvdata(cl->dev);
    638	struct imx_rproc *priv = rproc->priv;
    639
    640	queue_work(priv->workqueue, &priv->rproc_work);
    641}
    642
    643static int imx_rproc_xtr_mbox_init(struct rproc *rproc)
    644{
    645	struct imx_rproc *priv = rproc->priv;
    646	struct device *dev = priv->dev;
    647	struct mbox_client *cl;
    648	int ret;
    649
    650	if (!of_get_property(dev->of_node, "mbox-names", NULL))
    651		return 0;
    652
    653	cl = &priv->cl;
    654	cl->dev = dev;
    655	cl->tx_block = true;
    656	cl->tx_tout = 100;
    657	cl->knows_txdone = false;
    658	cl->rx_callback = imx_rproc_rx_callback;
    659
    660	priv->tx_ch = mbox_request_channel_byname(cl, "tx");
    661	if (IS_ERR(priv->tx_ch)) {
    662		ret = PTR_ERR(priv->tx_ch);
    663		return dev_err_probe(cl->dev, ret,
    664				     "failed to request tx mailbox channel: %d\n", ret);
    665	}
    666
    667	priv->rx_ch = mbox_request_channel_byname(cl, "rx");
    668	if (IS_ERR(priv->rx_ch)) {
    669		mbox_free_channel(priv->tx_ch);
    670		ret = PTR_ERR(priv->rx_ch);
    671		return dev_err_probe(cl->dev, ret,
    672				     "failed to request rx mailbox channel: %d\n", ret);
    673	}
    674
    675	return 0;
    676}
    677
    678static void imx_rproc_free_mbox(struct rproc *rproc)
    679{
    680	struct imx_rproc *priv = rproc->priv;
    681
    682	mbox_free_channel(priv->tx_ch);
    683	mbox_free_channel(priv->rx_ch);
    684}
    685
    686static int imx_rproc_detect_mode(struct imx_rproc *priv)
    687{
    688	struct regmap_config config = { .name = "imx-rproc" };
    689	const struct imx_rproc_dcfg *dcfg = priv->dcfg;
    690	struct device *dev = priv->dev;
    691	struct regmap *regmap;
    692	struct arm_smccc_res res;
    693	int ret;
    694	u32 val;
    695
    696	switch (dcfg->method) {
    697	case IMX_RPROC_NONE:
    698		priv->rproc->state = RPROC_DETACHED;
    699		return 0;
    700	case IMX_RPROC_SMC:
    701		arm_smccc_smc(IMX_SIP_RPROC, IMX_SIP_RPROC_STARTED, 0, 0, 0, 0, 0, 0, &res);
    702		if (res.a0)
    703			priv->rproc->state = RPROC_DETACHED;
    704		return 0;
    705	default:
    706		break;
    707	}
    708
    709	regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon");
    710	if (IS_ERR(regmap)) {
    711		dev_err(dev, "failed to find syscon\n");
    712		return PTR_ERR(regmap);
    713	}
    714
    715	priv->regmap = regmap;
    716	regmap_attach_dev(dev, regmap, &config);
    717
    718	ret = regmap_read(regmap, dcfg->src_reg, &val);
    719	if (ret) {
    720		dev_err(dev, "Failed to read src\n");
    721		return ret;
    722	}
    723
    724	if ((val & dcfg->src_mask) != dcfg->src_stop)
    725		priv->rproc->state = RPROC_DETACHED;
    726
    727	return 0;
    728}
    729
    730static int imx_rproc_clk_enable(struct imx_rproc *priv)
    731{
    732	const struct imx_rproc_dcfg *dcfg = priv->dcfg;
    733	struct device *dev = priv->dev;
    734	int ret;
    735
    736	/* Remote core is not under control of Linux */
    737	if (dcfg->method == IMX_RPROC_NONE)
    738		return 0;
    739
    740	priv->clk = devm_clk_get(dev, NULL);
    741	if (IS_ERR(priv->clk)) {
    742		dev_err(dev, "Failed to get clock\n");
    743		return PTR_ERR(priv->clk);
    744	}
    745
    746	/*
    747	 * clk for M4 block including memory. Should be
    748	 * enabled before .start for FW transfer.
    749	 */
    750	ret = clk_prepare_enable(priv->clk);
    751	if (ret) {
    752		dev_err(dev, "Failed to enable clock\n");
    753		return ret;
    754	}
    755
    756	return 0;
    757}
    758
    759static int imx_rproc_probe(struct platform_device *pdev)
    760{
    761	struct device *dev = &pdev->dev;
    762	struct device_node *np = dev->of_node;
    763	struct imx_rproc *priv;
    764	struct rproc *rproc;
    765	const struct imx_rproc_dcfg *dcfg;
    766	int ret;
    767
    768	/* set some other name then imx */
    769	rproc = rproc_alloc(dev, "imx-rproc", &imx_rproc_ops,
    770			    NULL, sizeof(*priv));
    771	if (!rproc)
    772		return -ENOMEM;
    773
    774	dcfg = of_device_get_match_data(dev);
    775	if (!dcfg) {
    776		ret = -EINVAL;
    777		goto err_put_rproc;
    778	}
    779
    780	priv = rproc->priv;
    781	priv->rproc = rproc;
    782	priv->dcfg = dcfg;
    783	priv->dev = dev;
    784
    785	dev_set_drvdata(dev, rproc);
    786	priv->workqueue = create_workqueue(dev_name(dev));
    787	if (!priv->workqueue) {
    788		dev_err(dev, "cannot create workqueue\n");
    789		ret = -ENOMEM;
    790		goto err_put_rproc;
    791	}
    792
    793	ret = imx_rproc_xtr_mbox_init(rproc);
    794	if (ret)
    795		goto err_put_wkq;
    796
    797	ret = imx_rproc_addr_init(priv, pdev);
    798	if (ret) {
    799		dev_err(dev, "failed on imx_rproc_addr_init\n");
    800		goto err_put_mbox;
    801	}
    802
    803	ret = imx_rproc_detect_mode(priv);
    804	if (ret)
    805		goto err_put_mbox;
    806
    807	ret = imx_rproc_clk_enable(priv);
    808	if (ret)
    809		goto err_put_mbox;
    810
    811	INIT_WORK(&priv->rproc_work, imx_rproc_vq_work);
    812
    813	if (rproc->state != RPROC_DETACHED)
    814		rproc->auto_boot = of_property_read_bool(np, "fsl,auto-boot");
    815
    816	ret = rproc_add(rproc);
    817	if (ret) {
    818		dev_err(dev, "rproc_add failed\n");
    819		goto err_put_clk;
    820	}
    821
    822	return 0;
    823
    824err_put_clk:
    825	clk_disable_unprepare(priv->clk);
    826err_put_mbox:
    827	imx_rproc_free_mbox(rproc);
    828err_put_wkq:
    829	destroy_workqueue(priv->workqueue);
    830err_put_rproc:
    831	rproc_free(rproc);
    832
    833	return ret;
    834}
    835
    836static int imx_rproc_remove(struct platform_device *pdev)
    837{
    838	struct rproc *rproc = platform_get_drvdata(pdev);
    839	struct imx_rproc *priv = rproc->priv;
    840
    841	clk_disable_unprepare(priv->clk);
    842	rproc_del(rproc);
    843	imx_rproc_free_mbox(rproc);
    844	destroy_workqueue(priv->workqueue);
    845	rproc_free(rproc);
    846
    847	return 0;
    848}
    849
    850static const struct of_device_id imx_rproc_of_match[] = {
    851	{ .compatible = "fsl,imx7ulp-cm4", .data = &imx_rproc_cfg_imx7ulp },
    852	{ .compatible = "fsl,imx7d-cm4", .data = &imx_rproc_cfg_imx7d },
    853	{ .compatible = "fsl,imx6sx-cm4", .data = &imx_rproc_cfg_imx6sx },
    854	{ .compatible = "fsl,imx8mq-cm4", .data = &imx_rproc_cfg_imx8mq },
    855	{ .compatible = "fsl,imx8mm-cm4", .data = &imx_rproc_cfg_imx8mq },
    856	{ .compatible = "fsl,imx8mn-cm7", .data = &imx_rproc_cfg_imx8mn },
    857	{ .compatible = "fsl,imx8mp-cm7", .data = &imx_rproc_cfg_imx8mn },
    858	{ .compatible = "fsl,imx8ulp-cm33", .data = &imx_rproc_cfg_imx8ulp },
    859	{ .compatible = "fsl,imx93-cm33", .data = &imx_rproc_cfg_imx93 },
    860	{},
    861};
    862MODULE_DEVICE_TABLE(of, imx_rproc_of_match);
    863
    864static struct platform_driver imx_rproc_driver = {
    865	.probe = imx_rproc_probe,
    866	.remove = imx_rproc_remove,
    867	.driver = {
    868		.name = "imx-rproc",
    869		.of_match_table = imx_rproc_of_match,
    870	},
    871};
    872
    873module_platform_driver(imx_rproc_driver);
    874
    875MODULE_LICENSE("GPL v2");
    876MODULE_DESCRIPTION("i.MX remote processor control driver");
    877MODULE_AUTHOR("Oleksij Rempel <o.rempel@pengutronix.de>");