blob: 2a1cccd8d311ea9615e7b65152f587ad3e7a9045 [file] [log] [blame]
Fabien Dessenne13140de2019-05-14 10:26:58 +02001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
4 * Authors: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics.
5 * Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics.
6 */
7
8#include <linux/arm-smccc.h>
9#include <linux/dma-mapping.h>
10#include <linux/interrupt.h>
11#include <linux/io.h>
12#include <linux/mailbox_client.h>
13#include <linux/mfd/syscon.h>
14#include <linux/module.h>
15#include <linux/of_address.h>
16#include <linux/of_device.h>
17#include <linux/of_reserved_mem.h>
Fabien Dessenne410119e2019-08-26 17:38:43 +020018#include <linux/pm_wakeirq.h>
Fabien Dessenne13140de2019-05-14 10:26:58 +020019#include <linux/regmap.h>
20#include <linux/remoteproc.h>
21#include <linux/reset.h>
Michael S. Tsirkinbf02bd92020-04-09 17:09:35 -040022#include <linux/slab.h>
Arnaud Pouliquen714cf5e2019-10-25 10:56:39 +020023#include <linux/workqueue.h>
Fabien Dessenne13140de2019-05-14 10:26:58 +020024
25#include "remoteproc_internal.h"
26
27#define HOLD_BOOT 0
28#define RELEASE_BOOT 1
29
30#define MBOX_NB_VQ 2
31#define MBOX_NB_MBX 3
32
33#define STM32_SMC_RCC 0x82001000
34#define STM32_SMC_REG_WRITE 0x1
35
36#define STM32_MBX_VQ0 "vq0"
Arnaud Pouliquen714cf5e2019-10-25 10:56:39 +020037#define STM32_MBX_VQ0_ID 0
Fabien Dessenne13140de2019-05-14 10:26:58 +020038#define STM32_MBX_VQ1 "vq1"
Arnaud Pouliquen714cf5e2019-10-25 10:56:39 +020039#define STM32_MBX_VQ1_ID 1
Fabien Dessenne13140de2019-05-14 10:26:58 +020040#define STM32_MBX_SHUTDOWN "shutdown"
41
Mathieu Poirier376ffdc2020-07-14 14:04:40 -060042#define M4_STATE_OFF 0
43#define M4_STATE_INI 1
44#define M4_STATE_CRUN 2
45#define M4_STATE_CSTOP 3
46#define M4_STATE_STANDBY 4
47#define M4_STATE_CRASH 5
48
Fabien Dessenne13140de2019-05-14 10:26:58 +020049struct stm32_syscon {
50 struct regmap *map;
51 u32 reg;
52 u32 mask;
53};
54
55struct stm32_rproc_mem {
56 char name[20];
57 void __iomem *cpu_addr;
58 phys_addr_t bus_addr;
59 u32 dev_addr;
60 size_t size;
61};
62
63struct stm32_rproc_mem_ranges {
64 u32 dev_addr;
65 u32 bus_addr;
66 u32 size;
67};
68
69struct stm32_mbox {
70 const unsigned char name[10];
71 struct mbox_chan *chan;
72 struct mbox_client client;
Arnaud Pouliquen714cf5e2019-10-25 10:56:39 +020073 struct work_struct vq_work;
Fabien Dessenne13140de2019-05-14 10:26:58 +020074 int vq_id;
75};
76
77struct stm32_rproc {
78 struct reset_control *rst;
79 struct stm32_syscon hold_boot;
80 struct stm32_syscon pdds;
Mathieu Poirier92765362020-07-14 14:04:39 -060081 struct stm32_syscon m4_state;
82 struct stm32_syscon rsctbl;
Fabien Dessenne410119e2019-08-26 17:38:43 +020083 int wdg_irq;
Fabien Dessenne13140de2019-05-14 10:26:58 +020084 u32 nb_rmems;
85 struct stm32_rproc_mem *rmems;
86 struct stm32_mbox mb[MBOX_NB_MBX];
Arnaud Pouliquen714cf5e2019-10-25 10:56:39 +020087 struct workqueue_struct *workqueue;
Fabien Dessenne13140de2019-05-14 10:26:58 +020088 bool secured_soc;
89};
90
91static int stm32_rproc_pa_to_da(struct rproc *rproc, phys_addr_t pa, u64 *da)
92{
93 unsigned int i;
94 struct stm32_rproc *ddata = rproc->priv;
95 struct stm32_rproc_mem *p_mem;
96
97 for (i = 0; i < ddata->nb_rmems; i++) {
98 p_mem = &ddata->rmems[i];
99
100 if (pa < p_mem->bus_addr ||
101 pa >= p_mem->bus_addr + p_mem->size)
102 continue;
103 *da = pa - p_mem->bus_addr + p_mem->dev_addr;
104 dev_dbg(rproc->dev.parent, "pa %pa to da %llx\n", &pa, *da);
105 return 0;
106 }
107
108 return -EINVAL;
109}
110
111static int stm32_rproc_mem_alloc(struct rproc *rproc,
112 struct rproc_mem_entry *mem)
113{
114 struct device *dev = rproc->dev.parent;
115 void *va;
116
117 dev_dbg(dev, "map memory: %pa+%x\n", &mem->dma, mem->len);
118 va = ioremap_wc(mem->dma, mem->len);
119 if (IS_ERR_OR_NULL(va)) {
120 dev_err(dev, "Unable to map memory region: %pa+%x\n",
121 &mem->dma, mem->len);
122 return -ENOMEM;
123 }
124
125 /* Update memory entry va */
126 mem->va = va;
127
128 return 0;
129}
130
131static int stm32_rproc_mem_release(struct rproc *rproc,
132 struct rproc_mem_entry *mem)
133{
134 dev_dbg(rproc->dev.parent, "unmap memory: %pa\n", &mem->dma);
135 iounmap(mem->va);
136
137 return 0;
138}
139
Mathieu Poirier7b9f18c2020-07-14 14:04:35 -0600140static int stm32_rproc_of_memory_translations(struct platform_device *pdev,
141 struct stm32_rproc *ddata)
Fabien Dessenne13140de2019-05-14 10:26:58 +0200142{
Mathieu Poirier7b9f18c2020-07-14 14:04:35 -0600143 struct device *parent, *dev = &pdev->dev;
Fabien Dessenne13140de2019-05-14 10:26:58 +0200144 struct device_node *np;
145 struct stm32_rproc_mem *p_mems;
146 struct stm32_rproc_mem_ranges *mem_range;
147 int cnt, array_size, i, ret = 0;
148
149 parent = dev->parent;
150 np = parent->of_node;
151
152 cnt = of_property_count_elems_of_size(np, "dma-ranges",
153 sizeof(*mem_range));
154 if (cnt <= 0) {
155 dev_err(dev, "%s: dma-ranges property not defined\n", __func__);
156 return -EINVAL;
157 }
158
159 p_mems = devm_kcalloc(dev, cnt, sizeof(*p_mems), GFP_KERNEL);
160 if (!p_mems)
161 return -ENOMEM;
162 mem_range = kcalloc(cnt, sizeof(*mem_range), GFP_KERNEL);
163 if (!mem_range)
164 return -ENOMEM;
165
166 array_size = cnt * sizeof(struct stm32_rproc_mem_ranges) / sizeof(u32);
167
168 ret = of_property_read_u32_array(np, "dma-ranges",
169 (u32 *)mem_range, array_size);
170 if (ret) {
171 dev_err(dev, "error while get dma-ranges property: %x\n", ret);
172 goto free_mem;
173 }
174
175 for (i = 0; i < cnt; i++) {
176 p_mems[i].bus_addr = mem_range[i].bus_addr;
177 p_mems[i].dev_addr = mem_range[i].dev_addr;
178 p_mems[i].size = mem_range[i].size;
179
180 dev_dbg(dev, "memory range[%i]: da %#x, pa %pa, size %#zx:\n",
181 i, p_mems[i].dev_addr, &p_mems[i].bus_addr,
182 p_mems[i].size);
183 }
184
185 ddata->rmems = p_mems;
186 ddata->nb_rmems = cnt;
187
188free_mem:
189 kfree(mem_range);
190 return ret;
191}
192
193static int stm32_rproc_mbox_idx(struct rproc *rproc, const unsigned char *name)
194{
195 struct stm32_rproc *ddata = rproc->priv;
196 int i;
197
198 for (i = 0; i < ARRAY_SIZE(ddata->mb); i++) {
199 if (!strncmp(ddata->mb[i].name, name, strlen(name)))
200 return i;
201 }
202 dev_err(&rproc->dev, "mailbox %s not found\n", name);
203
204 return -EINVAL;
205}
206
207static int stm32_rproc_elf_load_rsc_table(struct rproc *rproc,
208 const struct firmware *fw)
209{
210 if (rproc_elf_load_rsc_table(rproc, fw))
211 dev_warn(&rproc->dev, "no resource table found for this firmware\n");
212
213 return 0;
214}
215
Mathieu Poirierdadbdb92020-07-14 14:04:42 -0600216static int stm32_rproc_parse_memory_regions(struct rproc *rproc)
Fabien Dessenne13140de2019-05-14 10:26:58 +0200217{
218 struct device *dev = rproc->dev.parent;
219 struct device_node *np = dev->of_node;
220 struct of_phandle_iterator it;
221 struct rproc_mem_entry *mem;
222 struct reserved_mem *rmem;
223 u64 da;
224 int index = 0;
225
226 /* Register associated reserved memory regions */
227 of_phandle_iterator_init(&it, np, "memory-region", NULL, 0);
228 while (of_phandle_iterator_next(&it) == 0) {
229 rmem = of_reserved_mem_lookup(it.node);
230 if (!rmem) {
231 dev_err(dev, "unable to acquire memory-region\n");
232 return -EINVAL;
233 }
234
235 if (stm32_rproc_pa_to_da(rproc, rmem->base, &da) < 0) {
236 dev_err(dev, "memory region not valid %pa\n",
237 &rmem->base);
238 return -EINVAL;
239 }
240
241 /* No need to map vdev buffer */
242 if (strcmp(it.node->name, "vdev0buffer")) {
243 /* Register memory region */
244 mem = rproc_mem_entry_init(dev, NULL,
245 (dma_addr_t)rmem->base,
246 rmem->size, da,
247 stm32_rproc_mem_alloc,
248 stm32_rproc_mem_release,
249 it.node->name);
250
251 if (mem)
252 rproc_coredump_add_segment(rproc, da,
253 rmem->size);
254 } else {
255 /* Register reserved memory for vdev buffer alloc */
256 mem = rproc_of_resm_mem_entry_init(dev, index,
257 rmem->size,
258 rmem->base,
259 it.node->name);
260 }
261
262 if (!mem)
263 return -ENOMEM;
264
265 rproc_add_carveout(rproc, mem);
266 index++;
267 }
268
Mathieu Poirierdadbdb92020-07-14 14:04:42 -0600269 return 0;
270}
271
272static int stm32_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw)
273{
274 int ret = stm32_rproc_parse_memory_regions(rproc);
275
276 if (ret)
277 return ret;
278
Fabien Dessenne13140de2019-05-14 10:26:58 +0200279 return stm32_rproc_elf_load_rsc_table(rproc, fw);
280}
281
282static irqreturn_t stm32_rproc_wdg(int irq, void *data)
283{
Mathieu Poirierb8631ab2020-07-14 14:04:36 -0600284 struct platform_device *pdev = data;
285 struct rproc *rproc = platform_get_drvdata(pdev);
Fabien Dessenne13140de2019-05-14 10:26:58 +0200286
287 rproc_report_crash(rproc, RPROC_WATCHDOG);
288
289 return IRQ_HANDLED;
290}
291
Arnaud Pouliquen714cf5e2019-10-25 10:56:39 +0200292static void stm32_rproc_mb_vq_work(struct work_struct *work)
293{
294 struct stm32_mbox *mb = container_of(work, struct stm32_mbox, vq_work);
295 struct rproc *rproc = dev_get_drvdata(mb->client.dev);
296
297 if (rproc_vq_interrupt(rproc, mb->vq_id) == IRQ_NONE)
298 dev_dbg(&rproc->dev, "no message found in vq%d\n", mb->vq_id);
299}
300
Fabien Dessenne13140de2019-05-14 10:26:58 +0200301static void stm32_rproc_mb_callback(struct mbox_client *cl, void *data)
302{
303 struct rproc *rproc = dev_get_drvdata(cl->dev);
304 struct stm32_mbox *mb = container_of(cl, struct stm32_mbox, client);
Arnaud Pouliquen714cf5e2019-10-25 10:56:39 +0200305 struct stm32_rproc *ddata = rproc->priv;
Fabien Dessenne13140de2019-05-14 10:26:58 +0200306
Arnaud Pouliquen714cf5e2019-10-25 10:56:39 +0200307 queue_work(ddata->workqueue, &mb->vq_work);
Fabien Dessenne13140de2019-05-14 10:26:58 +0200308}
309
310static void stm32_rproc_free_mbox(struct rproc *rproc)
311{
312 struct stm32_rproc *ddata = rproc->priv;
313 unsigned int i;
314
315 for (i = 0; i < ARRAY_SIZE(ddata->mb); i++) {
316 if (ddata->mb[i].chan)
317 mbox_free_channel(ddata->mb[i].chan);
318 ddata->mb[i].chan = NULL;
319 }
320}
321
322static const struct stm32_mbox stm32_rproc_mbox[MBOX_NB_MBX] = {
323 {
324 .name = STM32_MBX_VQ0,
Arnaud Pouliquen714cf5e2019-10-25 10:56:39 +0200325 .vq_id = STM32_MBX_VQ0_ID,
Fabien Dessenne13140de2019-05-14 10:26:58 +0200326 .client = {
327 .rx_callback = stm32_rproc_mb_callback,
328 .tx_block = false,
329 },
330 },
331 {
332 .name = STM32_MBX_VQ1,
Arnaud Pouliquen714cf5e2019-10-25 10:56:39 +0200333 .vq_id = STM32_MBX_VQ1_ID,
Fabien Dessenne13140de2019-05-14 10:26:58 +0200334 .client = {
335 .rx_callback = stm32_rproc_mb_callback,
336 .tx_block = false,
337 },
338 },
339 {
340 .name = STM32_MBX_SHUTDOWN,
341 .vq_id = -1,
342 .client = {
343 .tx_block = true,
344 .tx_done = NULL,
345 .tx_tout = 500, /* 500 ms time out */
346 },
347 }
348};
349
Fabien Dessenne4a56e4232019-11-15 11:03:08 +0100350static int stm32_rproc_request_mbox(struct rproc *rproc)
Fabien Dessenne13140de2019-05-14 10:26:58 +0200351{
352 struct stm32_rproc *ddata = rproc->priv;
353 struct device *dev = &rproc->dev;
354 unsigned int i;
Fabien Dessenne4a56e4232019-11-15 11:03:08 +0100355 int j;
Fabien Dessenne13140de2019-05-14 10:26:58 +0200356 const unsigned char *name;
357 struct mbox_client *cl;
358
359 /* Initialise mailbox structure table */
360 memcpy(ddata->mb, stm32_rproc_mbox, sizeof(stm32_rproc_mbox));
361
362 for (i = 0; i < MBOX_NB_MBX; i++) {
363 name = ddata->mb[i].name;
364
365 cl = &ddata->mb[i].client;
366 cl->dev = dev->parent;
367
368 ddata->mb[i].chan = mbox_request_channel_byname(cl, name);
369 if (IS_ERR(ddata->mb[i].chan)) {
Fabien Dessenne4a56e4232019-11-15 11:03:08 +0100370 if (PTR_ERR(ddata->mb[i].chan) == -EPROBE_DEFER)
371 goto err_probe;
Fabien Dessenne13140de2019-05-14 10:26:58 +0200372 dev_warn(dev, "cannot get %s mbox\n", name);
373 ddata->mb[i].chan = NULL;
374 }
Arnaud Pouliquen714cf5e2019-10-25 10:56:39 +0200375 if (ddata->mb[i].vq_id >= 0) {
376 INIT_WORK(&ddata->mb[i].vq_work,
377 stm32_rproc_mb_vq_work);
378 }
Fabien Dessenne13140de2019-05-14 10:26:58 +0200379 }
Fabien Dessenne4a56e4232019-11-15 11:03:08 +0100380
381 return 0;
382
383err_probe:
384 for (j = i - 1; j >= 0; j--)
385 if (ddata->mb[j].chan)
386 mbox_free_channel(ddata->mb[j].chan);
387 return -EPROBE_DEFER;
Fabien Dessenne13140de2019-05-14 10:26:58 +0200388}
389
390static int stm32_rproc_set_hold_boot(struct rproc *rproc, bool hold)
391{
392 struct stm32_rproc *ddata = rproc->priv;
393 struct stm32_syscon hold_boot = ddata->hold_boot;
394 struct arm_smccc_res smc_res;
395 int val, err;
396
397 val = hold ? HOLD_BOOT : RELEASE_BOOT;
398
Arnd Bergmann93f1d3e2019-07-08 14:42:51 +0200399 if (IS_ENABLED(CONFIG_HAVE_ARM_SMCCC) && ddata->secured_soc) {
Fabien Dessenne13140de2019-05-14 10:26:58 +0200400 arm_smccc_smc(STM32_SMC_RCC, STM32_SMC_REG_WRITE,
401 hold_boot.reg, val, 0, 0, 0, 0, &smc_res);
402 err = smc_res.a0;
403 } else {
404 err = regmap_update_bits(hold_boot.map, hold_boot.reg,
405 hold_boot.mask, val);
406 }
407
408 if (err)
409 dev_err(&rproc->dev, "failed to set hold boot\n");
410
411 return err;
412}
413
414static void stm32_rproc_add_coredump_trace(struct rproc *rproc)
415{
416 struct rproc_debug_trace *trace;
417 struct rproc_dump_segment *segment;
418 bool already_added;
419
420 list_for_each_entry(trace, &rproc->traces, node) {
421 already_added = false;
422
423 list_for_each_entry(segment, &rproc->dump_segments, node) {
424 if (segment->da == trace->trace_mem.da) {
425 already_added = true;
426 break;
427 }
428 }
429
430 if (!already_added)
431 rproc_coredump_add_segment(rproc, trace->trace_mem.da,
432 trace->trace_mem.len);
433 }
434}
435
436static int stm32_rproc_start(struct rproc *rproc)
437{
Fabien Dessenneabbe4292019-08-26 17:38:06 +0200438 struct stm32_rproc *ddata = rproc->priv;
Fabien Dessenne13140de2019-05-14 10:26:58 +0200439 int err;
440
441 stm32_rproc_add_coredump_trace(rproc);
442
Fabien Dessenneabbe4292019-08-26 17:38:06 +0200443 /* clear remote proc Deep Sleep */
444 if (ddata->pdds.map) {
445 err = regmap_update_bits(ddata->pdds.map, ddata->pdds.reg,
446 ddata->pdds.mask, 0);
447 if (err) {
448 dev_err(&rproc->dev, "failed to clear pdds\n");
449 return err;
450 }
451 }
452
Fabien Dessenne13140de2019-05-14 10:26:58 +0200453 err = stm32_rproc_set_hold_boot(rproc, false);
454 if (err)
455 return err;
456
457 return stm32_rproc_set_hold_boot(rproc, true);
458}
459
460static int stm32_rproc_stop(struct rproc *rproc)
461{
462 struct stm32_rproc *ddata = rproc->priv;
463 int err, dummy_data, idx;
464
465 /* request shutdown of the remote processor */
466 if (rproc->state != RPROC_OFFLINE) {
467 idx = stm32_rproc_mbox_idx(rproc, STM32_MBX_SHUTDOWN);
468 if (idx >= 0 && ddata->mb[idx].chan) {
469 /* a dummy data is sent to allow to block on transmit */
470 err = mbox_send_message(ddata->mb[idx].chan,
471 &dummy_data);
472 if (err < 0)
473 dev_warn(&rproc->dev, "warning: remote FW shutdown without ack\n");
474 }
475 }
476
477 err = stm32_rproc_set_hold_boot(rproc, true);
478 if (err)
479 return err;
480
481 err = reset_control_assert(ddata->rst);
482 if (err) {
483 dev_err(&rproc->dev, "failed to assert the reset\n");
484 return err;
485 }
486
487 /* to allow platform Standby power mode, set remote proc Deep Sleep */
488 if (ddata->pdds.map) {
489 err = regmap_update_bits(ddata->pdds.map, ddata->pdds.reg,
490 ddata->pdds.mask, 1);
491 if (err) {
492 dev_err(&rproc->dev, "failed to set pdds\n");
493 return err;
494 }
495 }
496
497 return 0;
498}
499
500static void stm32_rproc_kick(struct rproc *rproc, int vqid)
501{
502 struct stm32_rproc *ddata = rproc->priv;
503 unsigned int i;
504 int err;
505
506 if (WARN_ON(vqid >= MBOX_NB_VQ))
507 return;
508
509 for (i = 0; i < MBOX_NB_MBX; i++) {
510 if (vqid != ddata->mb[i].vq_id)
511 continue;
512 if (!ddata->mb[i].chan)
513 return;
514 err = mbox_send_message(ddata->mb[i].chan, (void *)(long)vqid);
515 if (err < 0)
516 dev_err(&rproc->dev, "%s: failed (%s, err:%d)\n",
517 __func__, ddata->mb[i].name, err);
518 return;
519 }
520}
521
522static struct rproc_ops st_rproc_ops = {
523 .start = stm32_rproc_start,
524 .stop = stm32_rproc_stop,
525 .kick = stm32_rproc_kick,
526 .load = rproc_elf_load_segments,
527 .parse_fw = stm32_rproc_parse_fw,
528 .find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table,
Clement Legere29ff72b2020-04-22 11:30:17 +0200529 .sanity_check = rproc_elf_sanity_check,
Fabien Dessenne13140de2019-05-14 10:26:58 +0200530 .get_boot_addr = rproc_elf_get_boot_addr,
531};
532
533static const struct of_device_id stm32_rproc_match[] = {
534 { .compatible = "st,stm32mp1-m4" },
535 {},
536};
537MODULE_DEVICE_TABLE(of, stm32_rproc_match);
538
539static int stm32_rproc_get_syscon(struct device_node *np, const char *prop,
540 struct stm32_syscon *syscon)
541{
542 int err = 0;
543
544 syscon->map = syscon_regmap_lookup_by_phandle(np, prop);
545 if (IS_ERR(syscon->map)) {
546 err = PTR_ERR(syscon->map);
547 syscon->map = NULL;
548 goto out;
549 }
550
551 err = of_property_read_u32_index(np, prop, 1, &syscon->reg);
552 if (err)
553 goto out;
554
555 err = of_property_read_u32_index(np, prop, 2, &syscon->mask);
556
557out:
558 return err;
559}
560
Mathieu Poirier8210fc82020-07-14 14:04:37 -0600561static int stm32_rproc_parse_dt(struct platform_device *pdev,
562 struct stm32_rproc *ddata, bool *auto_boot)
Fabien Dessenne13140de2019-05-14 10:26:58 +0200563{
564 struct device *dev = &pdev->dev;
565 struct device_node *np = dev->of_node;
Fabien Dessenne13140de2019-05-14 10:26:58 +0200566 struct stm32_syscon tz;
567 unsigned int tzen;
568 int err, irq;
569
570 irq = platform_get_irq(pdev, 0);
Fabien Dessenned333de32019-08-26 17:38:29 +0200571 if (irq == -EPROBE_DEFER)
572 return -EPROBE_DEFER;
573
Fabien Dessenne13140de2019-05-14 10:26:58 +0200574 if (irq > 0) {
575 err = devm_request_irq(dev, irq, stm32_rproc_wdg, 0,
Mathieu Poirierb8631ab2020-07-14 14:04:36 -0600576 dev_name(dev), pdev);
Fabien Dessenne13140de2019-05-14 10:26:58 +0200577 if (err) {
578 dev_err(dev, "failed to request wdg irq\n");
579 return err;
580 }
581
Fabien Dessenne410119e2019-08-26 17:38:43 +0200582 ddata->wdg_irq = irq;
583
584 if (of_property_read_bool(np, "wakeup-source")) {
585 device_init_wakeup(dev, true);
586 dev_pm_set_wake_irq(dev, irq);
587 }
588
Fabien Dessenne13140de2019-05-14 10:26:58 +0200589 dev_info(dev, "wdg irq registered\n");
590 }
591
592 ddata->rst = devm_reset_control_get_by_index(dev, 0);
593 if (IS_ERR(ddata->rst)) {
594 dev_err(dev, "failed to get mcu reset\n");
595 return PTR_ERR(ddata->rst);
596 }
597
598 /*
599 * if platform is secured the hold boot bit must be written by
600 * smc call and read normally.
601 * if not secure the hold boot bit could be read/write normally
602 */
603 err = stm32_rproc_get_syscon(np, "st,syscfg-tz", &tz);
604 if (err) {
605 dev_err(dev, "failed to get tz syscfg\n");
606 return err;
607 }
608
609 err = regmap_read(tz.map, tz.reg, &tzen);
610 if (err) {
Mathieu Poirier8210fc82020-07-14 14:04:37 -0600611 dev_err(dev, "failed to read tzen\n");
Fabien Dessenne13140de2019-05-14 10:26:58 +0200612 return err;
613 }
614 ddata->secured_soc = tzen & tz.mask;
615
616 err = stm32_rproc_get_syscon(np, "st,syscfg-holdboot",
617 &ddata->hold_boot);
618 if (err) {
619 dev_err(dev, "failed to get hold boot\n");
620 return err;
621 }
622
623 err = stm32_rproc_get_syscon(np, "st,syscfg-pdds", &ddata->pdds);
624 if (err)
Ahmad Fatoumb1f0fa82020-02-24 18:25:19 +0100625 dev_info(dev, "failed to get pdds\n");
Fabien Dessenne13140de2019-05-14 10:26:58 +0200626
Mathieu Poirier8210fc82020-07-14 14:04:37 -0600627 *auto_boot = of_property_read_bool(np, "st,auto-boot");
Fabien Dessenne13140de2019-05-14 10:26:58 +0200628
Mathieu Poirier92765362020-07-14 14:04:39 -0600629 /*
630 * See if we can check the M4 status, i.e if it was started
631 * from the boot loader or not.
632 */
633 err = stm32_rproc_get_syscon(np, "st,syscfg-m4-state",
634 &ddata->m4_state);
635 if (err) {
636 /* remember this */
637 ddata->m4_state.map = NULL;
638 /* no coprocessor state syscon (optional) */
639 dev_warn(dev, "m4 state not supported\n");
640
641 /* no need to go further */
642 return 0;
643 }
644
645 /* See if we can get the resource table */
646 err = stm32_rproc_get_syscon(np, "st,syscfg-rsc-tbl",
647 &ddata->rsctbl);
648 if (err) {
649 /* no rsc table syscon (optional) */
650 dev_warn(dev, "rsc tbl syscon not supported\n");
651 }
652
Mathieu Poirier95e32f82020-07-14 14:04:38 -0600653 return 0;
Fabien Dessenne13140de2019-05-14 10:26:58 +0200654}
655
Mathieu Poirier376ffdc2020-07-14 14:04:40 -0600656static int stm32_rproc_get_m4_status(struct stm32_rproc *ddata,
657 unsigned int *state)
658{
659 /* See stm32_rproc_parse_dt() */
660 if (!ddata->m4_state.map) {
661 /*
662 * We couldn't get the coprocessor's state, assume
663 * it is not running.
664 */
665 state = M4_STATE_OFF;
666 return 0;
667 }
668
669 return regmap_read(ddata->m4_state.map, ddata->m4_state.reg, state);
670}
671
Fabien Dessenne13140de2019-05-14 10:26:58 +0200672static int stm32_rproc_probe(struct platform_device *pdev)
673{
674 struct device *dev = &pdev->dev;
675 struct stm32_rproc *ddata;
676 struct device_node *np = dev->of_node;
677 struct rproc *rproc;
Mathieu Poirier376ffdc2020-07-14 14:04:40 -0600678 unsigned int state;
Fabien Dessenne13140de2019-05-14 10:26:58 +0200679 int ret;
680
681 ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
682 if (ret)
683 return ret;
684
685 rproc = rproc_alloc(dev, np->name, &st_rproc_ops, NULL, sizeof(*ddata));
686 if (!rproc)
687 return -ENOMEM;
688
Fabien Dessenne13140de2019-05-14 10:26:58 +0200689 ddata = rproc->priv;
Mathieu Poirier8210fc82020-07-14 14:04:37 -0600690
691 rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_NONE);
692
693 ret = stm32_rproc_parse_dt(pdev, ddata, &rproc->auto_boot);
694 if (ret)
695 goto free_rproc;
696
Mathieu Poirier95e32f82020-07-14 14:04:38 -0600697 ret = stm32_rproc_of_memory_translations(pdev, ddata);
698 if (ret)
699 goto free_rproc;
700
Mathieu Poirier376ffdc2020-07-14 14:04:40 -0600701 ret = stm32_rproc_get_m4_status(ddata, &state);
702 if (ret)
703 goto free_rproc;
704
Mathieu Poirierdadbdb92020-07-14 14:04:42 -0600705 if (state == M4_STATE_CRUN) {
Mathieu Poirier376ffdc2020-07-14 14:04:40 -0600706 rproc->state = RPROC_DETACHED;
707
Mathieu Poirierdadbdb92020-07-14 14:04:42 -0600708 ret = stm32_rproc_parse_memory_regions(rproc);
709 if (ret)
710 goto free_resources;
711 }
712
Mathieu Poirier8210fc82020-07-14 14:04:37 -0600713 rproc->has_iommu = false;
Arnaud Pouliquen714cf5e2019-10-25 10:56:39 +0200714 ddata->workqueue = create_workqueue(dev_name(dev));
715 if (!ddata->workqueue) {
716 dev_err(dev, "cannot create workqueue\n");
717 ret = -ENOMEM;
Mathieu Poirierdadbdb92020-07-14 14:04:42 -0600718 goto free_resources;
Arnaud Pouliquen714cf5e2019-10-25 10:56:39 +0200719 }
Fabien Dessenne13140de2019-05-14 10:26:58 +0200720
721 platform_set_drvdata(pdev, rproc);
722
Fabien Dessenne4a56e4232019-11-15 11:03:08 +0100723 ret = stm32_rproc_request_mbox(rproc);
724 if (ret)
Mathieu Poirier8210fc82020-07-14 14:04:37 -0600725 goto free_wkq;
Fabien Dessenne13140de2019-05-14 10:26:58 +0200726
727 ret = rproc_add(rproc);
728 if (ret)
729 goto free_mb;
730
731 return 0;
732
733free_mb:
734 stm32_rproc_free_mbox(rproc);
Arnaud Pouliquen714cf5e2019-10-25 10:56:39 +0200735free_wkq:
736 destroy_workqueue(ddata->workqueue);
Mathieu Poirierdadbdb92020-07-14 14:04:42 -0600737free_resources:
738 rproc_resource_cleanup(rproc);
Fabien Dessenne13140de2019-05-14 10:26:58 +0200739free_rproc:
Fabien Dessenne410119e2019-08-26 17:38:43 +0200740 if (device_may_wakeup(dev)) {
741 dev_pm_clear_wake_irq(dev);
742 device_init_wakeup(dev, false);
743 }
Fabien Dessenne13140de2019-05-14 10:26:58 +0200744 rproc_free(rproc);
745 return ret;
746}
747
748static int stm32_rproc_remove(struct platform_device *pdev)
749{
750 struct rproc *rproc = platform_get_drvdata(pdev);
Arnaud Pouliquen714cf5e2019-10-25 10:56:39 +0200751 struct stm32_rproc *ddata = rproc->priv;
Fabien Dessenne410119e2019-08-26 17:38:43 +0200752 struct device *dev = &pdev->dev;
Fabien Dessenne13140de2019-05-14 10:26:58 +0200753
754 if (atomic_read(&rproc->power) > 0)
755 rproc_shutdown(rproc);
756
757 rproc_del(rproc);
758 stm32_rproc_free_mbox(rproc);
Arnaud Pouliquen714cf5e2019-10-25 10:56:39 +0200759 destroy_workqueue(ddata->workqueue);
Fabien Dessenne410119e2019-08-26 17:38:43 +0200760
761 if (device_may_wakeup(dev)) {
762 dev_pm_clear_wake_irq(dev);
763 device_init_wakeup(dev, false);
764 }
Fabien Dessenne13140de2019-05-14 10:26:58 +0200765 rproc_free(rproc);
766
767 return 0;
768}
769
Fabien Dessenne410119e2019-08-26 17:38:43 +0200770static int __maybe_unused stm32_rproc_suspend(struct device *dev)
771{
772 struct rproc *rproc = dev_get_drvdata(dev);
773 struct stm32_rproc *ddata = rproc->priv;
774
775 if (device_may_wakeup(dev))
776 return enable_irq_wake(ddata->wdg_irq);
777
778 return 0;
779}
780
781static int __maybe_unused stm32_rproc_resume(struct device *dev)
782{
783 struct rproc *rproc = dev_get_drvdata(dev);
784 struct stm32_rproc *ddata = rproc->priv;
785
786 if (device_may_wakeup(dev))
787 return disable_irq_wake(ddata->wdg_irq);
788
789 return 0;
790}
791
792static SIMPLE_DEV_PM_OPS(stm32_rproc_pm_ops,
793 stm32_rproc_suspend, stm32_rproc_resume);
794
Fabien Dessenne13140de2019-05-14 10:26:58 +0200795static struct platform_driver stm32_rproc_driver = {
796 .probe = stm32_rproc_probe,
797 .remove = stm32_rproc_remove,
798 .driver = {
799 .name = "stm32-rproc",
Fabien Dessenne410119e2019-08-26 17:38:43 +0200800 .pm = &stm32_rproc_pm_ops,
Fabien Dessenne13140de2019-05-14 10:26:58 +0200801 .of_match_table = of_match_ptr(stm32_rproc_match),
802 },
803};
804module_platform_driver(stm32_rproc_driver);
805
806MODULE_DESCRIPTION("STM32 Remote Processor Control Driver");
807MODULE_AUTHOR("Ludovic Barre <ludovic.barre@st.com>");
808MODULE_AUTHOR("Fabien Dessenne <fabien.dessenne@st.com>");
809MODULE_LICENSE("GPL v2");
810