for (i = 0; i < ARRAY_SIZE(ddata->mb); i++) { if (!strncmp(ddata->mb[i].name, name, strlen(name))) return i;
}
dev_err(&rproc->dev, "mailbox %s not found\n", name);
return -EINVAL;
}
staticint stm32_rproc_prepare(struct rproc *rproc)
{ struct device *dev = rproc->dev.parent; struct device_node *np = dev->of_node; struct of_phandle_iterator it; struct rproc_mem_entry *mem; struct reserved_mem *rmem;
u64 da; int index = 0;
/* Register associated reserved memory regions */
of_phandle_iterator_init(&it, np, "memory-region", NULL, 0); while (of_phandle_iterator_next(&it) == 0) {
rmem = of_reserved_mem_lookup(it.node); if (!rmem) {
of_node_put(it.node);
dev_err(dev, "unable to acquire memory-region\n"); return -EINVAL;
}
if (stm32_rproc_pa_to_da(rproc, rmem->base, &da) < 0) {
of_node_put(it.node);
dev_err(dev, "memory region not valid %pa\n",
&rmem->base); return -EINVAL;
}
/* No need to map vdev buffer */ if (strcmp(it.node->name, "vdev0buffer")) { /* Register memory region */
mem = rproc_mem_entry_init(dev, NULL,
(dma_addr_t)rmem->base,
rmem->size, da,
stm32_rproc_mem_alloc,
stm32_rproc_mem_release,
it.node->name);
if (mem)
rproc_coredump_add_segment(rproc, da,
rmem->size);
} else { /* Register reserved memory for vdev buffer alloc */
mem = rproc_of_resm_mem_entry_init(dev, index,
rmem->size,
rmem->base,
it.node->name);
}
if (!mem) {
of_node_put(it.node); return -ENOMEM;
}
rproc_add_carveout(rproc, mem);
index++;
}
return0;
}
staticint stm32_rproc_parse_fw(struct rproc *rproc, conststruct firmware *fw)
{ if (rproc_elf_load_rsc_table(rproc, fw))
dev_warn(&rproc->dev, "no resource table found for this firmware\n");
/* request shutdown of the remote processor */ if (rproc->state != RPROC_OFFLINE && rproc->state != RPROC_CRASHED) {
idx = stm32_rproc_mbox_idx(rproc, STM32_MBX_SHUTDOWN); if (idx >= 0 && ddata->mb[idx].chan) {
err = mbox_send_message(ddata->mb[idx].chan, "detach"); if (err < 0)
dev_warn(&rproc->dev, "warning: remote FW shutdown without ack\n");
}
}
err = stm32_rproc_set_hold_boot(rproc, true); if (err) return err;
err = reset_control_assert(ddata->rst); if (err) {
dev_err(&rproc->dev, "failed to assert the reset\n"); return err;
}
/* to allow platform Standby power mode, set remote proc Deep Sleep */ if (ddata->pdds.map) {
err = regmap_update_bits(ddata->pdds.map, ddata->pdds.reg,
ddata->pdds.mask, 1); if (err) {
dev_err(&rproc->dev, "failed to set pdds\n"); return err;
}
}
/* update coprocessor state to OFF if available */ if (ddata->m4_state.map) {
err = regmap_update_bits(ddata->m4_state.map,
ddata->m4_state.reg,
ddata->m4_state.mask,
M4_STATE_OFF); if (err) {
dev_err(&rproc->dev, "failed to set copro state\n"); return err;
}
}
return0;
}
staticvoid stm32_rproc_kick(struct rproc *rproc, int vqid)
{ struct stm32_rproc *ddata = rproc->priv; unsignedint i; int err;
if (WARN_ON(vqid >= MBOX_NB_VQ)) return;
for (i = 0; i < MBOX_NB_MBX; i++) { if (vqid != ddata->mb[i].vq_id) continue; if (!ddata->mb[i].chan) return;
err = mbox_send_message(ddata->mb[i].chan, "kick"); if (err < 0)
dev_err(&rproc->dev, "%s: failed (%s, err:%d)\n",
__func__, ddata->mb[i].name, err); return;
}
}
irq = platform_get_irq_optional(pdev, 0); if (irq == -EPROBE_DEFER) return irq;
if (irq > 0) {
err = devm_request_irq(dev, irq, stm32_rproc_wdg, 0,
dev_name(dev), pdev); if (err) return dev_err_probe(dev, err, "failed to request wdg irq\n");
ddata->wdg_irq = irq;
if (of_property_read_bool(np, "wakeup-source")) {
device_init_wakeup(dev, true);
dev_pm_set_wake_irq(dev, irq);
}
dev_info(dev, "wdg irq registered\n");
}
ddata->rst = devm_reset_control_get_optional(dev, "mcu_rst"); if (!ddata->rst) { /* Try legacy fallback method: get it by index */
ddata->rst = devm_reset_control_get_by_index(dev, 0);
} if (IS_ERR(ddata->rst)) return dev_err_probe(dev, PTR_ERR(ddata->rst), "failed to get mcu_reset\n");
ddata->hold_boot_rst = devm_reset_control_get_optional(dev, "hold_boot"); if (IS_ERR(ddata->hold_boot_rst)) return dev_err_probe(dev, PTR_ERR(ddata->hold_boot_rst), "failed to get hold_boot reset\n");
if (!ddata->hold_boot_rst && IS_ENABLED(CONFIG_HAVE_ARM_SMCCC)) { /* Manage the MCU_BOOT using SMC call */
err = stm32_rproc_get_syscon(np, "st,syscfg-tz", &tz); if (!err) {
err = regmap_read(tz.map, tz.reg, &tzen); if (err) {
dev_err(dev, "failed to read tzen\n"); return err;
}
ddata->hold_boot_smc = tzen & tz.mask;
}
}
if (!ddata->hold_boot_rst && !ddata->hold_boot_smc) { /* Default: hold boot manage it through the syscon controller */
err = stm32_rproc_get_syscon(np, "st,syscfg-holdboot",
&ddata->hold_boot); if (err) {
dev_err(dev, "failed to get hold boot\n"); return err;
}
}
err = stm32_rproc_get_syscon(np, "st,syscfg-pdds", &ddata->pdds); if (err)
dev_info(dev, "failed to get pdds\n");
/* *SeeifwecanchecktheM4status,i.eifitwasstarted *fromthebootloaderornot.
*/
err = stm32_rproc_get_syscon(np, "st,syscfg-m4-state",
&ddata->m4_state); if (err) { /* remember this */
ddata->m4_state.map = NULL; /* no coprocessor state syscon (optional) */
dev_warn(dev, "m4 state not supported\n");
/* no need to go further */ return0;
}
/* See if we can get the resource table */
err = stm32_rproc_get_syscon(np, "st,syscfg-rsc-tbl",
&ddata->rsctbl); if (err) { /* no rsc table syscon (optional) */
dev_warn(dev, "rsc tbl syscon not supported\n");
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.18Bemerkung:
(vorverarbeitet am 2026-09-29)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.