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

rcar_rproc.c (4720B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) IoT.bzh 2021
      4 */
      5
      6#include <linux/limits.h>
      7#include <linux/module.h>
      8#include <linux/of_device.h>
      9#include <linux/of_reserved_mem.h>
     10#include <linux/pm_runtime.h>
     11#include <linux/remoteproc.h>
     12#include <linux/reset.h>
     13#include <linux/soc/renesas/rcar-rst.h>
     14
     15#include "remoteproc_internal.h"
     16
     17struct rcar_rproc {
     18	struct reset_control *rst;
     19};
     20
     21static int rcar_rproc_mem_alloc(struct rproc *rproc,
     22				 struct rproc_mem_entry *mem)
     23{
     24	struct device *dev = &rproc->dev;
     25	void *va;
     26
     27	dev_dbg(dev, "map memory: %pa+%zx\n", &mem->dma, mem->len);
     28	va = ioremap_wc(mem->dma, mem->len);
     29	if (!va) {
     30		dev_err(dev, "Unable to map memory region: %pa+%zx\n",
     31			&mem->dma, mem->len);
     32		return -ENOMEM;
     33	}
     34
     35	/* Update memory entry va */
     36	mem->va = va;
     37
     38	return 0;
     39}
     40
     41static int rcar_rproc_mem_release(struct rproc *rproc,
     42				   struct rproc_mem_entry *mem)
     43{
     44	dev_dbg(&rproc->dev, "unmap memory: %pa\n", &mem->dma);
     45	iounmap(mem->va);
     46
     47	return 0;
     48}
     49
     50static int rcar_rproc_prepare(struct rproc *rproc)
     51{
     52	struct device *dev = rproc->dev.parent;
     53	struct device_node *np = dev->of_node;
     54	struct of_phandle_iterator it;
     55	struct rproc_mem_entry *mem;
     56	struct reserved_mem *rmem;
     57	u32 da;
     58
     59	/* Register associated reserved memory regions */
     60	of_phandle_iterator_init(&it, np, "memory-region", NULL, 0);
     61	while (of_phandle_iterator_next(&it) == 0) {
     62
     63		rmem = of_reserved_mem_lookup(it.node);
     64		if (!rmem) {
     65			dev_err(&rproc->dev,
     66				"unable to acquire memory-region\n");
     67			return -EINVAL;
     68		}
     69
     70		if (rmem->base > U32_MAX)
     71			return -EINVAL;
     72
     73		/* No need to translate pa to da, R-Car use same map */
     74		da = rmem->base;
     75		mem = rproc_mem_entry_init(dev, NULL,
     76					   rmem->base,
     77					   rmem->size, da,
     78					   rcar_rproc_mem_alloc,
     79					   rcar_rproc_mem_release,
     80					   it.node->name);
     81
     82		if (!mem)
     83			return -ENOMEM;
     84
     85		rproc_add_carveout(rproc, mem);
     86	}
     87
     88	return 0;
     89}
     90
     91static int rcar_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw)
     92{
     93	int ret;
     94
     95	ret = rproc_elf_load_rsc_table(rproc, fw);
     96	if (ret)
     97		dev_info(&rproc->dev, "No resource table in elf\n");
     98
     99	return 0;
    100}
    101
    102static int rcar_rproc_start(struct rproc *rproc)
    103{
    104	struct rcar_rproc *priv = rproc->priv;
    105	int err;
    106
    107	if (!rproc->bootaddr)
    108		return -EINVAL;
    109
    110	err = rcar_rst_set_rproc_boot_addr(rproc->bootaddr);
    111	if (err) {
    112		dev_err(&rproc->dev, "failed to set rproc boot addr\n");
    113		return err;
    114	}
    115
    116	err = reset_control_deassert(priv->rst);
    117	if (err)
    118		dev_err(&rproc->dev, "failed to deassert reset\n");
    119
    120	return err;
    121}
    122
    123static int rcar_rproc_stop(struct rproc *rproc)
    124{
    125	struct rcar_rproc *priv = rproc->priv;
    126	int err;
    127
    128	err = reset_control_assert(priv->rst);
    129	if (err)
    130		dev_err(&rproc->dev, "failed to assert reset\n");
    131
    132	return err;
    133}
    134
    135static struct rproc_ops rcar_rproc_ops = {
    136	.prepare	= rcar_rproc_prepare,
    137	.start		= rcar_rproc_start,
    138	.stop		= rcar_rproc_stop,
    139	.load		= rproc_elf_load_segments,
    140	.parse_fw	= rcar_rproc_parse_fw,
    141	.find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table,
    142	.sanity_check	= rproc_elf_sanity_check,
    143	.get_boot_addr	= rproc_elf_get_boot_addr,
    144
    145};
    146
    147static int rcar_rproc_probe(struct platform_device *pdev)
    148{
    149	struct device *dev = &pdev->dev;
    150	struct device_node *np = dev->of_node;
    151	struct rcar_rproc *priv;
    152	struct rproc *rproc;
    153	int ret;
    154
    155	rproc = devm_rproc_alloc(dev, np->name, &rcar_rproc_ops,
    156				NULL, sizeof(*priv));
    157	if (!rproc)
    158		return -ENOMEM;
    159
    160	priv = rproc->priv;
    161
    162	priv->rst = devm_reset_control_get_exclusive(dev, NULL);
    163	if (IS_ERR(priv->rst)) {
    164		ret = PTR_ERR(priv->rst);
    165		dev_err_probe(dev, ret, "fail to acquire rproc reset\n");
    166		return ret;
    167	}
    168
    169	pm_runtime_enable(dev);
    170	ret = pm_runtime_resume_and_get(dev);
    171	if (ret) {
    172		dev_err(dev, "failed to power up\n");
    173		return ret;
    174	}
    175
    176	dev_set_drvdata(dev, rproc);
    177
    178	/* Manually start the rproc */
    179	rproc->auto_boot = false;
    180
    181	ret = devm_rproc_add(dev, rproc);
    182	if (ret) {
    183		dev_err(dev, "rproc_add failed\n");
    184		goto pm_disable;
    185	}
    186
    187	return 0;
    188
    189pm_disable:
    190	pm_runtime_disable(dev);
    191
    192	return ret;
    193}
    194
    195static int rcar_rproc_remove(struct platform_device *pdev)
    196{
    197	struct device *dev = &pdev->dev;
    198
    199	pm_runtime_disable(dev);
    200
    201	return 0;
    202}
    203
    204static const struct of_device_id rcar_rproc_of_match[] = {
    205	{ .compatible = "renesas,rcar-cr7" },
    206	{},
    207};
    208
    209MODULE_DEVICE_TABLE(of, rcar_rproc_of_match);
    210
    211static struct platform_driver rcar_rproc_driver = {
    212	.probe = rcar_rproc_probe,
    213	.remove = rcar_rproc_remove,
    214	.driver = {
    215		.name = "rcar-rproc",
    216		.of_match_table = rcar_rproc_of_match,
    217	},
    218};
    219
    220module_platform_driver(rcar_rproc_driver);
    221
    222MODULE_LICENSE("GPL v2");
    223MODULE_DESCRIPTION("Renesas R-Car Gen3 remote processor control driver");
    224MODULE_AUTHOR("Julien Massot <julien.massot@iot.bzh>");