1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) IoT.bzh 2021
6 #include <linux/limits.h>
7 #include <linux/module.h>
9 #include <linux/of_reserved_mem.h>
10 #include <linux/platform_device.h>
11 #include <linux/pm_runtime.h>
12 #include <linux/remoteproc.h>
13 #include <linux/reset.h>
14 #include <linux/soc/renesas/rcar-rst.h>
16 #include "remoteproc_internal.h"
19 struct reset_control
*rst
;
22 static int rcar_rproc_mem_alloc(struct rproc
*rproc
,
23 struct rproc_mem_entry
*mem
)
25 struct device
*dev
= &rproc
->dev
;
28 dev_dbg(dev
, "map memory: %pa+%zx\n", &mem
->dma
, mem
->len
);
29 va
= ioremap_wc(mem
->dma
, mem
->len
);
31 dev_err(dev
, "Unable to map memory region: %pa+%zx\n",
36 /* Update memory entry va */
42 static int rcar_rproc_mem_release(struct rproc
*rproc
,
43 struct rproc_mem_entry
*mem
)
45 dev_dbg(&rproc
->dev
, "unmap memory: %pa\n", &mem
->dma
);
51 static int rcar_rproc_prepare(struct rproc
*rproc
)
53 struct device
*dev
= rproc
->dev
.parent
;
54 struct device_node
*np
= dev
->of_node
;
55 struct of_phandle_iterator it
;
56 struct rproc_mem_entry
*mem
;
57 struct reserved_mem
*rmem
;
60 /* Register associated reserved memory regions */
61 of_phandle_iterator_init(&it
, np
, "memory-region", NULL
, 0);
62 while (of_phandle_iterator_next(&it
) == 0) {
64 rmem
= of_reserved_mem_lookup(it
.node
);
68 "unable to acquire memory-region\n");
72 if (rmem
->base
> U32_MAX
) {
77 /* No need to translate pa to da, R-Car use same map */
79 mem
= rproc_mem_entry_init(dev
, NULL
,
83 rcar_rproc_mem_release
,
91 rproc_add_carveout(rproc
, mem
);
97 static int rcar_rproc_parse_fw(struct rproc
*rproc
, const struct firmware
*fw
)
101 ret
= rproc_elf_load_rsc_table(rproc
, fw
);
103 dev_info(&rproc
->dev
, "No resource table in elf\n");
108 static int rcar_rproc_start(struct rproc
*rproc
)
110 struct rcar_rproc
*priv
= rproc
->priv
;
113 if (!rproc
->bootaddr
)
116 err
= rcar_rst_set_rproc_boot_addr(rproc
->bootaddr
);
118 dev_err(&rproc
->dev
, "failed to set rproc boot addr\n");
122 err
= reset_control_deassert(priv
->rst
);
124 dev_err(&rproc
->dev
, "failed to deassert reset\n");
129 static int rcar_rproc_stop(struct rproc
*rproc
)
131 struct rcar_rproc
*priv
= rproc
->priv
;
134 err
= reset_control_assert(priv
->rst
);
136 dev_err(&rproc
->dev
, "failed to assert reset\n");
141 static struct rproc_ops rcar_rproc_ops
= {
142 .prepare
= rcar_rproc_prepare
,
143 .start
= rcar_rproc_start
,
144 .stop
= rcar_rproc_stop
,
145 .load
= rproc_elf_load_segments
,
146 .parse_fw
= rcar_rproc_parse_fw
,
147 .find_loaded_rsc_table
= rproc_elf_find_loaded_rsc_table
,
148 .sanity_check
= rproc_elf_sanity_check
,
149 .get_boot_addr
= rproc_elf_get_boot_addr
,
153 static int rcar_rproc_probe(struct platform_device
*pdev
)
155 struct device
*dev
= &pdev
->dev
;
156 struct device_node
*np
= dev
->of_node
;
157 struct rcar_rproc
*priv
;
161 rproc
= devm_rproc_alloc(dev
, np
->name
, &rcar_rproc_ops
,
162 NULL
, sizeof(*priv
));
168 priv
->rst
= devm_reset_control_get_exclusive(dev
, NULL
);
169 if (IS_ERR(priv
->rst
)) {
170 ret
= PTR_ERR(priv
->rst
);
171 dev_err_probe(dev
, ret
, "fail to acquire rproc reset\n");
175 pm_runtime_enable(dev
);
176 ret
= pm_runtime_resume_and_get(dev
);
178 dev_err(dev
, "failed to power up\n");
182 dev_set_drvdata(dev
, rproc
);
184 /* Manually start the rproc */
185 rproc
->auto_boot
= false;
187 ret
= devm_rproc_add(dev
, rproc
);
189 dev_err(dev
, "rproc_add failed\n");
196 pm_runtime_disable(dev
);
201 static void rcar_rproc_remove(struct platform_device
*pdev
)
203 struct device
*dev
= &pdev
->dev
;
205 pm_runtime_disable(dev
);
208 static const struct of_device_id rcar_rproc_of_match
[] = {
209 { .compatible
= "renesas,rcar-cr7" },
213 MODULE_DEVICE_TABLE(of
, rcar_rproc_of_match
);
215 static struct platform_driver rcar_rproc_driver
= {
216 .probe
= rcar_rproc_probe
,
217 .remove
= rcar_rproc_remove
,
219 .name
= "rcar-rproc",
220 .of_match_table
= rcar_rproc_of_match
,
224 module_platform_driver(rcar_rproc_driver
);
226 MODULE_LICENSE("GPL v2");
227 MODULE_DESCRIPTION("Renesas R-Car Gen3 remote processor control driver");
228 MODULE_AUTHOR("Julien Massot <julien.massot@iot.bzh>");