1 | // 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.h> |
16 | #include <linux/of_reserved_mem.h> |
17 | #include <linux/platform_device.h> |
18 | #include <linux/pm_wakeirq.h> |
19 | #include <linux/regmap.h> |
20 | #include <linux/remoteproc.h> |
21 | #include <linux/reset.h> |
22 | #include <linux/slab.h> |
23 | #include <linux/workqueue.h> |
24 | |
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 4 |
32 | |
33 | #define STM32_SMC_RCC 0x82001000 |
34 | #define STM32_SMC_REG_WRITE 0x1 |
35 | |
36 | #define STM32_MBX_VQ0 "vq0" |
37 | #define STM32_MBX_VQ0_ID 0 |
38 | #define STM32_MBX_VQ1 "vq1" |
39 | #define STM32_MBX_VQ1_ID 1 |
40 | #define STM32_MBX_SHUTDOWN "shutdown" |
41 | #define STM32_MBX_DETACH "detach" |
42 | |
43 | #define RSC_TBL_SIZE 1024 |
44 | |
45 | #define M4_STATE_OFF 0 |
46 | #define M4_STATE_INI 1 |
47 | #define M4_STATE_CRUN 2 |
48 | #define M4_STATE_CSTOP 3 |
49 | #define M4_STATE_STANDBY 4 |
50 | #define M4_STATE_CRASH 5 |
51 | |
52 | struct stm32_syscon { |
53 | struct regmap *map; |
54 | u32 reg; |
55 | u32 mask; |
56 | }; |
57 | |
58 | struct stm32_rproc_mem { |
59 | char name[20]; |
60 | void __iomem *cpu_addr; |
61 | phys_addr_t bus_addr; |
62 | u32 dev_addr; |
63 | size_t size; |
64 | }; |
65 | |
66 | struct stm32_rproc_mem_ranges { |
67 | u32 dev_addr; |
68 | u32 bus_addr; |
69 | u32 size; |
70 | }; |
71 | |
72 | struct stm32_mbox { |
73 | const unsigned char name[10]; |
74 | struct mbox_chan *chan; |
75 | struct mbox_client client; |
76 | struct work_struct vq_work; |
77 | int vq_id; |
78 | }; |
79 | |
80 | struct stm32_rproc { |
81 | struct reset_control *rst; |
82 | struct reset_control *hold_boot_rst; |
83 | struct stm32_syscon hold_boot; |
84 | struct stm32_syscon pdds; |
85 | struct stm32_syscon m4_state; |
86 | struct stm32_syscon rsctbl; |
87 | int wdg_irq; |
88 | u32 nb_rmems; |
89 | struct stm32_rproc_mem *rmems; |
90 | struct stm32_mbox mb[MBOX_NB_MBX]; |
91 | struct workqueue_struct *workqueue; |
92 | bool hold_boot_smc; |
93 | void __iomem *rsc_va; |
94 | }; |
95 | |
96 | static int stm32_rproc_pa_to_da(struct rproc *rproc, phys_addr_t pa, u64 *da) |
97 | { |
98 | unsigned int i; |
99 | struct stm32_rproc *ddata = rproc->priv; |
100 | struct stm32_rproc_mem *p_mem; |
101 | |
102 | for (i = 0; i < ddata->nb_rmems; i++) { |
103 | p_mem = &ddata->rmems[i]; |
104 | |
105 | if (pa < p_mem->bus_addr || |
106 | pa >= p_mem->bus_addr + p_mem->size) |
107 | continue; |
108 | *da = pa - p_mem->bus_addr + p_mem->dev_addr; |
109 | dev_dbg(rproc->dev.parent, "pa %pa to da %llx\n" , &pa, *da); |
110 | return 0; |
111 | } |
112 | |
113 | return -EINVAL; |
114 | } |
115 | |
116 | static int stm32_rproc_mem_alloc(struct rproc *rproc, |
117 | struct rproc_mem_entry *mem) |
118 | { |
119 | struct device *dev = rproc->dev.parent; |
120 | void *va; |
121 | |
122 | dev_dbg(dev, "map memory: %pad+%zx\n" , &mem->dma, mem->len); |
123 | va = (__force void *)ioremap_wc(offset: mem->dma, size: mem->len); |
124 | if (IS_ERR_OR_NULL(ptr: va)) { |
125 | dev_err(dev, "Unable to map memory region: %pad+0x%zx\n" , |
126 | &mem->dma, mem->len); |
127 | return -ENOMEM; |
128 | } |
129 | |
130 | /* Update memory entry va */ |
131 | mem->va = va; |
132 | |
133 | return 0; |
134 | } |
135 | |
136 | static int stm32_rproc_mem_release(struct rproc *rproc, |
137 | struct rproc_mem_entry *mem) |
138 | { |
139 | dev_dbg(rproc->dev.parent, "unmap memory: %pa\n" , &mem->dma); |
140 | iounmap(addr: (__force __iomem void *)mem->va); |
141 | |
142 | return 0; |
143 | } |
144 | |
145 | static int stm32_rproc_of_memory_translations(struct platform_device *pdev, |
146 | struct stm32_rproc *ddata) |
147 | { |
148 | struct device *parent, *dev = &pdev->dev; |
149 | struct device_node *np; |
150 | struct stm32_rproc_mem *p_mems; |
151 | struct stm32_rproc_mem_ranges *mem_range; |
152 | int cnt, array_size, i, ret = 0; |
153 | |
154 | parent = dev->parent; |
155 | np = parent->of_node; |
156 | |
157 | cnt = of_property_count_elems_of_size(np, propname: "dma-ranges" , |
158 | elem_size: sizeof(*mem_range)); |
159 | if (cnt <= 0) { |
160 | dev_err(dev, "%s: dma-ranges property not defined\n" , __func__); |
161 | return -EINVAL; |
162 | } |
163 | |
164 | p_mems = devm_kcalloc(dev, n: cnt, size: sizeof(*p_mems), GFP_KERNEL); |
165 | if (!p_mems) |
166 | return -ENOMEM; |
167 | mem_range = kcalloc(n: cnt, size: sizeof(*mem_range), GFP_KERNEL); |
168 | if (!mem_range) |
169 | return -ENOMEM; |
170 | |
171 | array_size = cnt * sizeof(struct stm32_rproc_mem_ranges) / sizeof(u32); |
172 | |
173 | ret = of_property_read_u32_array(np, propname: "dma-ranges" , |
174 | out_values: (u32 *)mem_range, sz: array_size); |
175 | if (ret) { |
176 | dev_err(dev, "error while get dma-ranges property: %x\n" , ret); |
177 | goto free_mem; |
178 | } |
179 | |
180 | for (i = 0; i < cnt; i++) { |
181 | p_mems[i].bus_addr = mem_range[i].bus_addr; |
182 | p_mems[i].dev_addr = mem_range[i].dev_addr; |
183 | p_mems[i].size = mem_range[i].size; |
184 | |
185 | dev_dbg(dev, "memory range[%i]: da %#x, pa %pa, size %#zx:\n" , |
186 | i, p_mems[i].dev_addr, &p_mems[i].bus_addr, |
187 | p_mems[i].size); |
188 | } |
189 | |
190 | ddata->rmems = p_mems; |
191 | ddata->nb_rmems = cnt; |
192 | |
193 | free_mem: |
194 | kfree(objp: mem_range); |
195 | return ret; |
196 | } |
197 | |
198 | static int stm32_rproc_mbox_idx(struct rproc *rproc, const unsigned char *name) |
199 | { |
200 | struct stm32_rproc *ddata = rproc->priv; |
201 | int i; |
202 | |
203 | for (i = 0; i < ARRAY_SIZE(ddata->mb); i++) { |
204 | if (!strncmp(ddata->mb[i].name, name, strlen(name))) |
205 | return i; |
206 | } |
207 | dev_err(&rproc->dev, "mailbox %s not found\n" , name); |
208 | |
209 | return -EINVAL; |
210 | } |
211 | |
212 | static int stm32_rproc_prepare(struct rproc *rproc) |
213 | { |
214 | struct device *dev = rproc->dev.parent; |
215 | struct device_node *np = dev->of_node; |
216 | struct of_phandle_iterator it; |
217 | struct rproc_mem_entry *mem; |
218 | struct reserved_mem *rmem; |
219 | u64 da; |
220 | int index = 0; |
221 | |
222 | /* Register associated reserved memory regions */ |
223 | of_phandle_iterator_init(it: &it, np, list_name: "memory-region" , NULL, cell_count: 0); |
224 | while (of_phandle_iterator_next(it: &it) == 0) { |
225 | rmem = of_reserved_mem_lookup(np: it.node); |
226 | if (!rmem) { |
227 | of_node_put(node: it.node); |
228 | dev_err(dev, "unable to acquire memory-region\n" ); |
229 | return -EINVAL; |
230 | } |
231 | |
232 | if (stm32_rproc_pa_to_da(rproc, pa: rmem->base, da: &da) < 0) { |
233 | of_node_put(node: it.node); |
234 | dev_err(dev, "memory region not valid %pa\n" , |
235 | &rmem->base); |
236 | return -EINVAL; |
237 | } |
238 | |
239 | /* No need to map vdev buffer */ |
240 | if (strcmp(it.node->name, "vdev0buffer" )) { |
241 | /* Register memory region */ |
242 | mem = rproc_mem_entry_init(dev, NULL, |
243 | dma: (dma_addr_t)rmem->base, |
244 | len: rmem->size, da, |
245 | alloc: stm32_rproc_mem_alloc, |
246 | release: stm32_rproc_mem_release, |
247 | name: it.node->name); |
248 | |
249 | if (mem) |
250 | rproc_coredump_add_segment(rproc, da, |
251 | size: rmem->size); |
252 | } else { |
253 | /* Register reserved memory for vdev buffer alloc */ |
254 | mem = rproc_of_resm_mem_entry_init(dev, of_resm_idx: index, |
255 | len: rmem->size, |
256 | da: rmem->base, |
257 | name: it.node->name); |
258 | } |
259 | |
260 | if (!mem) { |
261 | of_node_put(node: it.node); |
262 | return -ENOMEM; |
263 | } |
264 | |
265 | rproc_add_carveout(rproc, mem); |
266 | index++; |
267 | } |
268 | |
269 | return 0; |
270 | } |
271 | |
272 | static int stm32_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw) |
273 | { |
274 | if (rproc_elf_load_rsc_table(rproc, fw)) |
275 | dev_warn(&rproc->dev, "no resource table found for this firmware\n" ); |
276 | |
277 | return 0; |
278 | } |
279 | |
280 | static irqreturn_t stm32_rproc_wdg(int irq, void *data) |
281 | { |
282 | struct platform_device *pdev = data; |
283 | struct rproc *rproc = platform_get_drvdata(pdev); |
284 | |
285 | rproc_report_crash(rproc, type: RPROC_WATCHDOG); |
286 | |
287 | return IRQ_HANDLED; |
288 | } |
289 | |
290 | static void stm32_rproc_mb_vq_work(struct work_struct *work) |
291 | { |
292 | struct stm32_mbox *mb = container_of(work, struct stm32_mbox, vq_work); |
293 | struct rproc *rproc = dev_get_drvdata(dev: mb->client.dev); |
294 | |
295 | mutex_lock(&rproc->lock); |
296 | |
297 | if (rproc->state != RPROC_RUNNING) |
298 | goto unlock_mutex; |
299 | |
300 | if (rproc_vq_interrupt(rproc, vq_id: mb->vq_id) == IRQ_NONE) |
301 | dev_dbg(&rproc->dev, "no message found in vq%d\n" , mb->vq_id); |
302 | |
303 | unlock_mutex: |
304 | mutex_unlock(lock: &rproc->lock); |
305 | } |
306 | |
307 | static void stm32_rproc_mb_callback(struct mbox_client *cl, void *data) |
308 | { |
309 | struct rproc *rproc = dev_get_drvdata(dev: cl->dev); |
310 | struct stm32_mbox *mb = container_of(cl, struct stm32_mbox, client); |
311 | struct stm32_rproc *ddata = rproc->priv; |
312 | |
313 | queue_work(wq: ddata->workqueue, work: &mb->vq_work); |
314 | } |
315 | |
316 | static void stm32_rproc_free_mbox(struct rproc *rproc) |
317 | { |
318 | struct stm32_rproc *ddata = rproc->priv; |
319 | unsigned int i; |
320 | |
321 | for (i = 0; i < ARRAY_SIZE(ddata->mb); i++) { |
322 | if (ddata->mb[i].chan) |
323 | mbox_free_channel(chan: ddata->mb[i].chan); |
324 | ddata->mb[i].chan = NULL; |
325 | } |
326 | } |
327 | |
328 | static const struct stm32_mbox stm32_rproc_mbox[MBOX_NB_MBX] = { |
329 | { |
330 | .name = STM32_MBX_VQ0, |
331 | .vq_id = STM32_MBX_VQ0_ID, |
332 | .client = { |
333 | .rx_callback = stm32_rproc_mb_callback, |
334 | .tx_block = false, |
335 | }, |
336 | }, |
337 | { |
338 | .name = STM32_MBX_VQ1, |
339 | .vq_id = STM32_MBX_VQ1_ID, |
340 | .client = { |
341 | .rx_callback = stm32_rproc_mb_callback, |
342 | .tx_block = false, |
343 | }, |
344 | }, |
345 | { |
346 | .name = STM32_MBX_SHUTDOWN, |
347 | .vq_id = -1, |
348 | .client = { |
349 | .tx_block = true, |
350 | .tx_done = NULL, |
351 | .tx_tout = 500, /* 500 ms time out */ |
352 | }, |
353 | }, |
354 | { |
355 | .name = STM32_MBX_DETACH, |
356 | .vq_id = -1, |
357 | .client = { |
358 | .tx_block = true, |
359 | .tx_done = NULL, |
360 | .tx_tout = 200, /* 200 ms time out to detach should be fair enough */ |
361 | }, |
362 | } |
363 | }; |
364 | |
365 | static int stm32_rproc_request_mbox(struct rproc *rproc) |
366 | { |
367 | struct stm32_rproc *ddata = rproc->priv; |
368 | struct device *dev = &rproc->dev; |
369 | unsigned int i; |
370 | int j; |
371 | const unsigned char *name; |
372 | struct mbox_client *cl; |
373 | |
374 | /* Initialise mailbox structure table */ |
375 | memcpy(ddata->mb, stm32_rproc_mbox, sizeof(stm32_rproc_mbox)); |
376 | |
377 | for (i = 0; i < MBOX_NB_MBX; i++) { |
378 | name = ddata->mb[i].name; |
379 | |
380 | cl = &ddata->mb[i].client; |
381 | cl->dev = dev->parent; |
382 | |
383 | ddata->mb[i].chan = mbox_request_channel_byname(cl, name); |
384 | if (IS_ERR(ptr: ddata->mb[i].chan)) { |
385 | if (PTR_ERR(ptr: ddata->mb[i].chan) == -EPROBE_DEFER) { |
386 | dev_err_probe(dev: dev->parent, |
387 | err: PTR_ERR(ptr: ddata->mb[i].chan), |
388 | fmt: "failed to request mailbox %s\n" , |
389 | name); |
390 | goto err_probe; |
391 | } |
392 | dev_warn(dev, "cannot get %s mbox\n" , name); |
393 | ddata->mb[i].chan = NULL; |
394 | } |
395 | if (ddata->mb[i].vq_id >= 0) { |
396 | INIT_WORK(&ddata->mb[i].vq_work, |
397 | stm32_rproc_mb_vq_work); |
398 | } |
399 | } |
400 | |
401 | return 0; |
402 | |
403 | err_probe: |
404 | for (j = i - 1; j >= 0; j--) |
405 | if (ddata->mb[j].chan) |
406 | mbox_free_channel(chan: ddata->mb[j].chan); |
407 | return -EPROBE_DEFER; |
408 | } |
409 | |
410 | static int stm32_rproc_set_hold_boot(struct rproc *rproc, bool hold) |
411 | { |
412 | struct stm32_rproc *ddata = rproc->priv; |
413 | struct stm32_syscon hold_boot = ddata->hold_boot; |
414 | struct arm_smccc_res smc_res; |
415 | int val, err; |
416 | |
417 | /* |
418 | * Three ways to manage the hold boot |
419 | * - using SCMI: the hold boot is managed as a reset, |
420 | * - using Linux(no SCMI): the hold boot is managed as a syscon register |
421 | * - using SMC call (deprecated): use SMC reset interface |
422 | */ |
423 | |
424 | val = hold ? HOLD_BOOT : RELEASE_BOOT; |
425 | |
426 | if (ddata->hold_boot_rst) { |
427 | /* Use the SCMI reset controller */ |
428 | if (!hold) |
429 | err = reset_control_deassert(rstc: ddata->hold_boot_rst); |
430 | else |
431 | err = reset_control_assert(rstc: ddata->hold_boot_rst); |
432 | } else if (IS_ENABLED(CONFIG_HAVE_ARM_SMCCC) && ddata->hold_boot_smc) { |
433 | /* Use the SMC call */ |
434 | arm_smccc_smc(STM32_SMC_RCC, STM32_SMC_REG_WRITE, |
435 | hold_boot.reg, val, 0, 0, 0, 0, &smc_res); |
436 | err = smc_res.a0; |
437 | } else { |
438 | /* Use syscon */ |
439 | err = regmap_update_bits(map: hold_boot.map, reg: hold_boot.reg, |
440 | mask: hold_boot.mask, val); |
441 | } |
442 | |
443 | if (err) |
444 | dev_err(&rproc->dev, "failed to set hold boot\n" ); |
445 | |
446 | return err; |
447 | } |
448 | |
449 | static void stm32_rproc_add_coredump_trace(struct rproc *rproc) |
450 | { |
451 | struct rproc_debug_trace *trace; |
452 | struct rproc_dump_segment *segment; |
453 | bool already_added; |
454 | |
455 | list_for_each_entry(trace, &rproc->traces, node) { |
456 | already_added = false; |
457 | |
458 | list_for_each_entry(segment, &rproc->dump_segments, node) { |
459 | if (segment->da == trace->trace_mem.da) { |
460 | already_added = true; |
461 | break; |
462 | } |
463 | } |
464 | |
465 | if (!already_added) |
466 | rproc_coredump_add_segment(rproc, da: trace->trace_mem.da, |
467 | size: trace->trace_mem.len); |
468 | } |
469 | } |
470 | |
471 | static int stm32_rproc_start(struct rproc *rproc) |
472 | { |
473 | struct stm32_rproc *ddata = rproc->priv; |
474 | int err; |
475 | |
476 | stm32_rproc_add_coredump_trace(rproc); |
477 | |
478 | /* clear remote proc Deep Sleep */ |
479 | if (ddata->pdds.map) { |
480 | err = regmap_update_bits(map: ddata->pdds.map, reg: ddata->pdds.reg, |
481 | mask: ddata->pdds.mask, val: 0); |
482 | if (err) { |
483 | dev_err(&rproc->dev, "failed to clear pdds\n" ); |
484 | return err; |
485 | } |
486 | } |
487 | |
488 | err = stm32_rproc_set_hold_boot(rproc, hold: false); |
489 | if (err) |
490 | return err; |
491 | |
492 | return stm32_rproc_set_hold_boot(rproc, hold: true); |
493 | } |
494 | |
495 | static int stm32_rproc_attach(struct rproc *rproc) |
496 | { |
497 | stm32_rproc_add_coredump_trace(rproc); |
498 | |
499 | return stm32_rproc_set_hold_boot(rproc, hold: true); |
500 | } |
501 | |
502 | static int stm32_rproc_detach(struct rproc *rproc) |
503 | { |
504 | struct stm32_rproc *ddata = rproc->priv; |
505 | int err, idx; |
506 | |
507 | /* Inform the remote processor of the detach */ |
508 | idx = stm32_rproc_mbox_idx(rproc, STM32_MBX_DETACH); |
509 | if (idx >= 0 && ddata->mb[idx].chan) { |
510 | err = mbox_send_message(chan: ddata->mb[idx].chan, mssg: "stop" ); |
511 | if (err < 0) |
512 | dev_warn(&rproc->dev, "warning: remote FW detach without ack\n" ); |
513 | } |
514 | |
515 | /* Allow remote processor to auto-reboot */ |
516 | return stm32_rproc_set_hold_boot(rproc, hold: false); |
517 | } |
518 | |
519 | static int stm32_rproc_stop(struct rproc *rproc) |
520 | { |
521 | struct stm32_rproc *ddata = rproc->priv; |
522 | int err, idx; |
523 | |
524 | /* request shutdown of the remote processor */ |
525 | if (rproc->state != RPROC_OFFLINE && rproc->state != RPROC_CRASHED) { |
526 | idx = stm32_rproc_mbox_idx(rproc, STM32_MBX_SHUTDOWN); |
527 | if (idx >= 0 && ddata->mb[idx].chan) { |
528 | err = mbox_send_message(chan: ddata->mb[idx].chan, mssg: "detach" ); |
529 | if (err < 0) |
530 | dev_warn(&rproc->dev, "warning: remote FW shutdown without ack\n" ); |
531 | } |
532 | } |
533 | |
534 | err = stm32_rproc_set_hold_boot(rproc, hold: true); |
535 | if (err) |
536 | return err; |
537 | |
538 | err = reset_control_assert(rstc: ddata->rst); |
539 | if (err) { |
540 | dev_err(&rproc->dev, "failed to assert the reset\n" ); |
541 | return err; |
542 | } |
543 | |
544 | /* to allow platform Standby power mode, set remote proc Deep Sleep */ |
545 | if (ddata->pdds.map) { |
546 | err = regmap_update_bits(map: ddata->pdds.map, reg: ddata->pdds.reg, |
547 | mask: ddata->pdds.mask, val: 1); |
548 | if (err) { |
549 | dev_err(&rproc->dev, "failed to set pdds\n" ); |
550 | return err; |
551 | } |
552 | } |
553 | |
554 | /* update coprocessor state to OFF if available */ |
555 | if (ddata->m4_state.map) { |
556 | err = regmap_update_bits(map: ddata->m4_state.map, |
557 | reg: ddata->m4_state.reg, |
558 | mask: ddata->m4_state.mask, |
559 | M4_STATE_OFF); |
560 | if (err) { |
561 | dev_err(&rproc->dev, "failed to set copro state\n" ); |
562 | return err; |
563 | } |
564 | } |
565 | |
566 | return 0; |
567 | } |
568 | |
569 | static void stm32_rproc_kick(struct rproc *rproc, int vqid) |
570 | { |
571 | struct stm32_rproc *ddata = rproc->priv; |
572 | unsigned int i; |
573 | int err; |
574 | |
575 | if (WARN_ON(vqid >= MBOX_NB_VQ)) |
576 | return; |
577 | |
578 | for (i = 0; i < MBOX_NB_MBX; i++) { |
579 | if (vqid != ddata->mb[i].vq_id) |
580 | continue; |
581 | if (!ddata->mb[i].chan) |
582 | return; |
583 | err = mbox_send_message(chan: ddata->mb[i].chan, mssg: "kick" ); |
584 | if (err < 0) |
585 | dev_err(&rproc->dev, "%s: failed (%s, err:%d)\n" , |
586 | __func__, ddata->mb[i].name, err); |
587 | return; |
588 | } |
589 | } |
590 | |
591 | static int stm32_rproc_da_to_pa(struct rproc *rproc, |
592 | u64 da, phys_addr_t *pa) |
593 | { |
594 | struct stm32_rproc *ddata = rproc->priv; |
595 | struct device *dev = rproc->dev.parent; |
596 | struct stm32_rproc_mem *p_mem; |
597 | unsigned int i; |
598 | |
599 | for (i = 0; i < ddata->nb_rmems; i++) { |
600 | p_mem = &ddata->rmems[i]; |
601 | |
602 | if (da < p_mem->dev_addr || |
603 | da >= p_mem->dev_addr + p_mem->size) |
604 | continue; |
605 | |
606 | *pa = da - p_mem->dev_addr + p_mem->bus_addr; |
607 | dev_dbg(dev, "da %llx to pa %pap\n" , da, pa); |
608 | |
609 | return 0; |
610 | } |
611 | |
612 | dev_err(dev, "can't translate da %llx\n" , da); |
613 | |
614 | return -EINVAL; |
615 | } |
616 | |
617 | static struct resource_table * |
618 | stm32_rproc_get_loaded_rsc_table(struct rproc *rproc, size_t *table_sz) |
619 | { |
620 | struct stm32_rproc *ddata = rproc->priv; |
621 | struct device *dev = rproc->dev.parent; |
622 | phys_addr_t rsc_pa; |
623 | u32 rsc_da; |
624 | int err; |
625 | |
626 | /* The resource table has already been mapped, nothing to do */ |
627 | if (ddata->rsc_va) |
628 | goto done; |
629 | |
630 | err = regmap_read(map: ddata->rsctbl.map, reg: ddata->rsctbl.reg, val: &rsc_da); |
631 | if (err) { |
632 | dev_err(dev, "failed to read rsc tbl addr\n" ); |
633 | return ERR_PTR(error: -EINVAL); |
634 | } |
635 | |
636 | if (!rsc_da) |
637 | /* no rsc table */ |
638 | return ERR_PTR(error: -ENOENT); |
639 | |
640 | err = stm32_rproc_da_to_pa(rproc, da: rsc_da, pa: &rsc_pa); |
641 | if (err) |
642 | return ERR_PTR(error: err); |
643 | |
644 | ddata->rsc_va = devm_ioremap_wc(dev, offset: rsc_pa, RSC_TBL_SIZE); |
645 | if (IS_ERR_OR_NULL(ptr: ddata->rsc_va)) { |
646 | dev_err(dev, "Unable to map memory region: %pa+%x\n" , |
647 | &rsc_pa, RSC_TBL_SIZE); |
648 | ddata->rsc_va = NULL; |
649 | return ERR_PTR(error: -ENOMEM); |
650 | } |
651 | |
652 | done: |
653 | /* |
654 | * Assuming the resource table fits in 1kB is fair. |
655 | * Notice for the detach, that this 1 kB memory area has to be reserved in the coprocessor |
656 | * firmware for the resource table. On detach, the remoteproc core re-initializes this |
657 | * entire area by overwriting it with the initial values stored in rproc->clean_table. |
658 | */ |
659 | *table_sz = RSC_TBL_SIZE; |
660 | return (__force struct resource_table *)ddata->rsc_va; |
661 | } |
662 | |
663 | static const struct rproc_ops st_rproc_ops = { |
664 | .prepare = stm32_rproc_prepare, |
665 | .start = stm32_rproc_start, |
666 | .stop = stm32_rproc_stop, |
667 | .attach = stm32_rproc_attach, |
668 | .detach = stm32_rproc_detach, |
669 | .kick = stm32_rproc_kick, |
670 | .load = rproc_elf_load_segments, |
671 | .parse_fw = stm32_rproc_parse_fw, |
672 | .find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table, |
673 | .get_loaded_rsc_table = stm32_rproc_get_loaded_rsc_table, |
674 | .sanity_check = rproc_elf_sanity_check, |
675 | .get_boot_addr = rproc_elf_get_boot_addr, |
676 | }; |
677 | |
678 | static const struct of_device_id stm32_rproc_match[] = { |
679 | { .compatible = "st,stm32mp1-m4" }, |
680 | {}, |
681 | }; |
682 | MODULE_DEVICE_TABLE(of, stm32_rproc_match); |
683 | |
684 | static int stm32_rproc_get_syscon(struct device_node *np, const char *prop, |
685 | struct stm32_syscon *syscon) |
686 | { |
687 | int err = 0; |
688 | |
689 | syscon->map = syscon_regmap_lookup_by_phandle(np, property: prop); |
690 | if (IS_ERR(ptr: syscon->map)) { |
691 | err = PTR_ERR(ptr: syscon->map); |
692 | syscon->map = NULL; |
693 | goto out; |
694 | } |
695 | |
696 | err = of_property_read_u32_index(np, propname: prop, index: 1, out_value: &syscon->reg); |
697 | if (err) |
698 | goto out; |
699 | |
700 | err = of_property_read_u32_index(np, propname: prop, index: 2, out_value: &syscon->mask); |
701 | |
702 | out: |
703 | return err; |
704 | } |
705 | |
706 | static int stm32_rproc_parse_dt(struct platform_device *pdev, |
707 | struct stm32_rproc *ddata, bool *auto_boot) |
708 | { |
709 | struct device *dev = &pdev->dev; |
710 | struct device_node *np = dev->of_node; |
711 | struct stm32_syscon tz; |
712 | unsigned int tzen; |
713 | int err, irq; |
714 | |
715 | irq = platform_get_irq_optional(pdev, 0); |
716 | if (irq == -EPROBE_DEFER) |
717 | return irq; |
718 | |
719 | if (irq > 0) { |
720 | err = devm_request_irq(dev, irq, handler: stm32_rproc_wdg, irqflags: 0, |
721 | devname: dev_name(dev), dev_id: pdev); |
722 | if (err) |
723 | return dev_err_probe(dev, err, |
724 | fmt: "failed to request wdg irq\n" ); |
725 | |
726 | ddata->wdg_irq = irq; |
727 | |
728 | if (of_property_read_bool(np, propname: "wakeup-source" )) { |
729 | device_init_wakeup(dev, enable: true); |
730 | dev_pm_set_wake_irq(dev, irq); |
731 | } |
732 | |
733 | dev_info(dev, "wdg irq registered\n" ); |
734 | } |
735 | |
736 | ddata->rst = devm_reset_control_get_optional(dev, id: "mcu_rst" ); |
737 | if (!ddata->rst) { |
738 | /* Try legacy fallback method: get it by index */ |
739 | ddata->rst = devm_reset_control_get_by_index(dev, index: 0); |
740 | } |
741 | if (IS_ERR(ptr: ddata->rst)) |
742 | return dev_err_probe(dev, err: PTR_ERR(ptr: ddata->rst), |
743 | fmt: "failed to get mcu_reset\n" ); |
744 | |
745 | /* |
746 | * Three ways to manage the hold boot |
747 | * - using SCMI: the hold boot is managed as a reset |
748 | * The DT "reset-mames" property should be defined with 2 items: |
749 | * reset-names = "mcu_rst", "hold_boot"; |
750 | * - using SMC call (deprecated): use SMC reset interface |
751 | * The DT "reset-mames" property is optional, "st,syscfg-tz" is required |
752 | * - default(no SCMI, no SMC): the hold boot is managed as a syscon register |
753 | * The DT "reset-mames" property is optional, "st,syscfg-holdboot" is required |
754 | */ |
755 | |
756 | ddata->hold_boot_rst = devm_reset_control_get_optional(dev, id: "hold_boot" ); |
757 | if (IS_ERR(ptr: ddata->hold_boot_rst)) |
758 | return dev_err_probe(dev, err: PTR_ERR(ptr: ddata->hold_boot_rst), |
759 | fmt: "failed to get hold_boot reset\n" ); |
760 | |
761 | if (!ddata->hold_boot_rst && IS_ENABLED(CONFIG_HAVE_ARM_SMCCC)) { |
762 | /* Manage the MCU_BOOT using SMC call */ |
763 | err = stm32_rproc_get_syscon(np, prop: "st,syscfg-tz" , syscon: &tz); |
764 | if (!err) { |
765 | err = regmap_read(map: tz.map, reg: tz.reg, val: &tzen); |
766 | if (err) { |
767 | dev_err(dev, "failed to read tzen\n" ); |
768 | return err; |
769 | } |
770 | ddata->hold_boot_smc = tzen & tz.mask; |
771 | } |
772 | } |
773 | |
774 | if (!ddata->hold_boot_rst && !ddata->hold_boot_smc) { |
775 | /* Default: hold boot manage it through the syscon controller */ |
776 | err = stm32_rproc_get_syscon(np, prop: "st,syscfg-holdboot" , |
777 | syscon: &ddata->hold_boot); |
778 | if (err) { |
779 | dev_err(dev, "failed to get hold boot\n" ); |
780 | return err; |
781 | } |
782 | } |
783 | |
784 | err = stm32_rproc_get_syscon(np, prop: "st,syscfg-pdds" , syscon: &ddata->pdds); |
785 | if (err) |
786 | dev_info(dev, "failed to get pdds\n" ); |
787 | |
788 | *auto_boot = of_property_read_bool(np, propname: "st,auto-boot" ); |
789 | |
790 | /* |
791 | * See if we can check the M4 status, i.e if it was started |
792 | * from the boot loader or not. |
793 | */ |
794 | err = stm32_rproc_get_syscon(np, prop: "st,syscfg-m4-state" , |
795 | syscon: &ddata->m4_state); |
796 | if (err) { |
797 | /* remember this */ |
798 | ddata->m4_state.map = NULL; |
799 | /* no coprocessor state syscon (optional) */ |
800 | dev_warn(dev, "m4 state not supported\n" ); |
801 | |
802 | /* no need to go further */ |
803 | return 0; |
804 | } |
805 | |
806 | /* See if we can get the resource table */ |
807 | err = stm32_rproc_get_syscon(np, prop: "st,syscfg-rsc-tbl" , |
808 | syscon: &ddata->rsctbl); |
809 | if (err) { |
810 | /* no rsc table syscon (optional) */ |
811 | dev_warn(dev, "rsc tbl syscon not supported\n" ); |
812 | } |
813 | |
814 | return 0; |
815 | } |
816 | |
817 | static int stm32_rproc_get_m4_status(struct stm32_rproc *ddata, |
818 | unsigned int *state) |
819 | { |
820 | /* See stm32_rproc_parse_dt() */ |
821 | if (!ddata->m4_state.map) { |
822 | /* |
823 | * We couldn't get the coprocessor's state, assume |
824 | * it is not running. |
825 | */ |
826 | *state = M4_STATE_OFF; |
827 | return 0; |
828 | } |
829 | |
830 | return regmap_read(map: ddata->m4_state.map, reg: ddata->m4_state.reg, val: state); |
831 | } |
832 | |
833 | static int stm32_rproc_probe(struct platform_device *pdev) |
834 | { |
835 | struct device *dev = &pdev->dev; |
836 | struct stm32_rproc *ddata; |
837 | struct device_node *np = dev->of_node; |
838 | struct rproc *rproc; |
839 | unsigned int state; |
840 | int ret; |
841 | |
842 | ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32)); |
843 | if (ret) |
844 | return ret; |
845 | |
846 | rproc = devm_rproc_alloc(dev, name: np->name, ops: &st_rproc_ops, NULL, len: sizeof(*ddata)); |
847 | if (!rproc) |
848 | return -ENOMEM; |
849 | |
850 | ddata = rproc->priv; |
851 | |
852 | rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_NONE); |
853 | |
854 | ret = stm32_rproc_parse_dt(pdev, ddata, auto_boot: &rproc->auto_boot); |
855 | if (ret) |
856 | goto free_rproc; |
857 | |
858 | ret = stm32_rproc_of_memory_translations(pdev, ddata); |
859 | if (ret) |
860 | goto free_rproc; |
861 | |
862 | ret = stm32_rproc_get_m4_status(ddata, state: &state); |
863 | if (ret) |
864 | goto free_rproc; |
865 | |
866 | if (state == M4_STATE_CRUN) |
867 | rproc->state = RPROC_DETACHED; |
868 | |
869 | rproc->has_iommu = false; |
870 | ddata->workqueue = create_workqueue(dev_name(dev)); |
871 | if (!ddata->workqueue) { |
872 | dev_err(dev, "cannot create workqueue\n" ); |
873 | ret = -ENOMEM; |
874 | goto free_resources; |
875 | } |
876 | |
877 | platform_set_drvdata(pdev, data: rproc); |
878 | |
879 | ret = stm32_rproc_request_mbox(rproc); |
880 | if (ret) |
881 | goto free_wkq; |
882 | |
883 | ret = rproc_add(rproc); |
884 | if (ret) |
885 | goto free_mb; |
886 | |
887 | return 0; |
888 | |
889 | free_mb: |
890 | stm32_rproc_free_mbox(rproc); |
891 | free_wkq: |
892 | destroy_workqueue(wq: ddata->workqueue); |
893 | free_resources: |
894 | rproc_resource_cleanup(rproc); |
895 | free_rproc: |
896 | if (device_may_wakeup(dev)) { |
897 | dev_pm_clear_wake_irq(dev); |
898 | device_init_wakeup(dev, enable: false); |
899 | } |
900 | return ret; |
901 | } |
902 | |
903 | static void stm32_rproc_remove(struct platform_device *pdev) |
904 | { |
905 | struct rproc *rproc = platform_get_drvdata(pdev); |
906 | struct stm32_rproc *ddata = rproc->priv; |
907 | struct device *dev = &pdev->dev; |
908 | |
909 | if (atomic_read(v: &rproc->power) > 0) |
910 | rproc_shutdown(rproc); |
911 | |
912 | rproc_del(rproc); |
913 | stm32_rproc_free_mbox(rproc); |
914 | destroy_workqueue(wq: ddata->workqueue); |
915 | |
916 | if (device_may_wakeup(dev)) { |
917 | dev_pm_clear_wake_irq(dev); |
918 | device_init_wakeup(dev, enable: false); |
919 | } |
920 | } |
921 | |
922 | static int stm32_rproc_suspend(struct device *dev) |
923 | { |
924 | struct rproc *rproc = dev_get_drvdata(dev); |
925 | struct stm32_rproc *ddata = rproc->priv; |
926 | |
927 | if (device_may_wakeup(dev)) |
928 | return enable_irq_wake(irq: ddata->wdg_irq); |
929 | |
930 | return 0; |
931 | } |
932 | |
933 | static int stm32_rproc_resume(struct device *dev) |
934 | { |
935 | struct rproc *rproc = dev_get_drvdata(dev); |
936 | struct stm32_rproc *ddata = rproc->priv; |
937 | |
938 | if (device_may_wakeup(dev)) |
939 | return disable_irq_wake(irq: ddata->wdg_irq); |
940 | |
941 | return 0; |
942 | } |
943 | |
944 | static DEFINE_SIMPLE_DEV_PM_OPS(stm32_rproc_pm_ops, |
945 | stm32_rproc_suspend, stm32_rproc_resume); |
946 | |
947 | static struct platform_driver stm32_rproc_driver = { |
948 | .probe = stm32_rproc_probe, |
949 | .remove_new = stm32_rproc_remove, |
950 | .driver = { |
951 | .name = "stm32-rproc" , |
952 | .pm = pm_ptr(&stm32_rproc_pm_ops), |
953 | .of_match_table = stm32_rproc_match, |
954 | }, |
955 | }; |
956 | module_platform_driver(stm32_rproc_driver); |
957 | |
958 | MODULE_DESCRIPTION("STM32 Remote Processor Control Driver" ); |
959 | MODULE_AUTHOR("Ludovic Barre <ludovic.barre@st.com>" ); |
960 | MODULE_AUTHOR("Fabien Dessenne <fabien.dessenne@st.com>" ); |
961 | MODULE_LICENSE("GPL v2" ); |
962 | |
963 | |