Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

remoteproc: stm32: add an ST stm32_rproc driver

This patch introduces a new remoteproc driver to control Cortex-M4
co-processor of the STM32 family.
It provides with the following features:
- start and stop
- dedicated co-processor memory regions registration
- coredump and recovery

Signed-off-by: Fabien Dessenne <fabien.dessenne@st.com>
Signed-off-by: Ludovic Barre <ludovic.barre@st.com>
Signed-off-by: Loic Pallardy <loic.pallardy@st.com>
Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>
[bjorn: Fixup of dev_dbg types and cast of int to pointer in mbox send]
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>

authored by

Fabien Dessenne and committed by
Bjorn Andersson
13140de0 6f576b43

+644
+15
drivers/remoteproc/Kconfig
··· 197 197 config ST_SLIM_REMOTEPROC 198 198 tristate 199 199 200 + config STM32_RPROC 201 + tristate "STM32 remoteproc support" 202 + depends on ARCH_STM32 203 + depends on REMOTEPROC 204 + select MAILBOX 205 + help 206 + Say y here to support STM32 MCU processors via the 207 + remote processor framework. 208 + 209 + You want to say y here in order to enable AMP 210 + use-cases to run on your platform (dedicated firmware could be 211 + offloaded to remote MCU processors using this framework). 212 + 213 + This can be either built-in or a loadable module. 214 + 200 215 endif # REMOTEPROC 201 216 202 217 endmenu
+1
drivers/remoteproc/Makefile
··· 26 26 qcom_wcnss_pil-y += qcom_wcnss_iris.o 27 27 obj-$(CONFIG_ST_REMOTEPROC) += st_remoteproc.o 28 28 obj-$(CONFIG_ST_SLIM_REMOTEPROC) += st_slim_rproc.o 29 + obj-$(CONFIG_STM32_RPROC) += stm32_rproc.o
+628
drivers/remoteproc/stm32_rproc.c
··· 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_address.h> 16 + #include <linux/of_device.h> 17 + #include <linux/of_reserved_mem.h> 18 + #include <linux/regmap.h> 19 + #include <linux/remoteproc.h> 20 + #include <linux/reset.h> 21 + 22 + #include "remoteproc_internal.h" 23 + 24 + #define HOLD_BOOT 0 25 + #define RELEASE_BOOT 1 26 + 27 + #define MBOX_NB_VQ 2 28 + #define MBOX_NB_MBX 3 29 + 30 + #define STM32_SMC_RCC 0x82001000 31 + #define STM32_SMC_REG_WRITE 0x1 32 + 33 + #define STM32_MBX_VQ0 "vq0" 34 + #define STM32_MBX_VQ1 "vq1" 35 + #define STM32_MBX_SHUTDOWN "shutdown" 36 + 37 + struct stm32_syscon { 38 + struct regmap *map; 39 + u32 reg; 40 + u32 mask; 41 + }; 42 + 43 + struct stm32_rproc_mem { 44 + char name[20]; 45 + void __iomem *cpu_addr; 46 + phys_addr_t bus_addr; 47 + u32 dev_addr; 48 + size_t size; 49 + }; 50 + 51 + struct stm32_rproc_mem_ranges { 52 + u32 dev_addr; 53 + u32 bus_addr; 54 + u32 size; 55 + }; 56 + 57 + struct stm32_mbox { 58 + const unsigned char name[10]; 59 + struct mbox_chan *chan; 60 + struct mbox_client client; 61 + int vq_id; 62 + }; 63 + 64 + struct stm32_rproc { 65 + struct reset_control *rst; 66 + struct stm32_syscon hold_boot; 67 + struct stm32_syscon pdds; 68 + u32 nb_rmems; 69 + struct stm32_rproc_mem *rmems; 70 + struct stm32_mbox mb[MBOX_NB_MBX]; 71 + bool secured_soc; 72 + }; 73 + 74 + static int stm32_rproc_pa_to_da(struct rproc *rproc, phys_addr_t pa, u64 *da) 75 + { 76 + unsigned int i; 77 + struct stm32_rproc *ddata = rproc->priv; 78 + struct stm32_rproc_mem *p_mem; 79 + 80 + for (i = 0; i < ddata->nb_rmems; i++) { 81 + p_mem = &ddata->rmems[i]; 82 + 83 + if (pa < p_mem->bus_addr || 84 + pa >= p_mem->bus_addr + p_mem->size) 85 + continue; 86 + *da = pa - p_mem->bus_addr + p_mem->dev_addr; 87 + dev_dbg(rproc->dev.parent, "pa %pa to da %llx\n", &pa, *da); 88 + return 0; 89 + } 90 + 91 + return -EINVAL; 92 + } 93 + 94 + static int stm32_rproc_mem_alloc(struct rproc *rproc, 95 + struct rproc_mem_entry *mem) 96 + { 97 + struct device *dev = rproc->dev.parent; 98 + void *va; 99 + 100 + dev_dbg(dev, "map memory: %pa+%x\n", &mem->dma, mem->len); 101 + va = ioremap_wc(mem->dma, mem->len); 102 + if (IS_ERR_OR_NULL(va)) { 103 + dev_err(dev, "Unable to map memory region: %pa+%x\n", 104 + &mem->dma, mem->len); 105 + return -ENOMEM; 106 + } 107 + 108 + /* Update memory entry va */ 109 + mem->va = va; 110 + 111 + return 0; 112 + } 113 + 114 + static int stm32_rproc_mem_release(struct rproc *rproc, 115 + struct rproc_mem_entry *mem) 116 + { 117 + dev_dbg(rproc->dev.parent, "unmap memory: %pa\n", &mem->dma); 118 + iounmap(mem->va); 119 + 120 + return 0; 121 + } 122 + 123 + static int stm32_rproc_of_memory_translations(struct rproc *rproc) 124 + { 125 + struct device *parent, *dev = rproc->dev.parent; 126 + struct stm32_rproc *ddata = rproc->priv; 127 + struct device_node *np; 128 + struct stm32_rproc_mem *p_mems; 129 + struct stm32_rproc_mem_ranges *mem_range; 130 + int cnt, array_size, i, ret = 0; 131 + 132 + parent = dev->parent; 133 + np = parent->of_node; 134 + 135 + cnt = of_property_count_elems_of_size(np, "dma-ranges", 136 + sizeof(*mem_range)); 137 + if (cnt <= 0) { 138 + dev_err(dev, "%s: dma-ranges property not defined\n", __func__); 139 + return -EINVAL; 140 + } 141 + 142 + p_mems = devm_kcalloc(dev, cnt, sizeof(*p_mems), GFP_KERNEL); 143 + if (!p_mems) 144 + return -ENOMEM; 145 + mem_range = kcalloc(cnt, sizeof(*mem_range), GFP_KERNEL); 146 + if (!mem_range) 147 + return -ENOMEM; 148 + 149 + array_size = cnt * sizeof(struct stm32_rproc_mem_ranges) / sizeof(u32); 150 + 151 + ret = of_property_read_u32_array(np, "dma-ranges", 152 + (u32 *)mem_range, array_size); 153 + if (ret) { 154 + dev_err(dev, "error while get dma-ranges property: %x\n", ret); 155 + goto free_mem; 156 + } 157 + 158 + for (i = 0; i < cnt; i++) { 159 + p_mems[i].bus_addr = mem_range[i].bus_addr; 160 + p_mems[i].dev_addr = mem_range[i].dev_addr; 161 + p_mems[i].size = mem_range[i].size; 162 + 163 + dev_dbg(dev, "memory range[%i]: da %#x, pa %pa, size %#zx:\n", 164 + i, p_mems[i].dev_addr, &p_mems[i].bus_addr, 165 + p_mems[i].size); 166 + } 167 + 168 + ddata->rmems = p_mems; 169 + ddata->nb_rmems = cnt; 170 + 171 + free_mem: 172 + kfree(mem_range); 173 + return ret; 174 + } 175 + 176 + static int stm32_rproc_mbox_idx(struct rproc *rproc, const unsigned char *name) 177 + { 178 + struct stm32_rproc *ddata = rproc->priv; 179 + int i; 180 + 181 + for (i = 0; i < ARRAY_SIZE(ddata->mb); i++) { 182 + if (!strncmp(ddata->mb[i].name, name, strlen(name))) 183 + return i; 184 + } 185 + dev_err(&rproc->dev, "mailbox %s not found\n", name); 186 + 187 + return -EINVAL; 188 + } 189 + 190 + static int stm32_rproc_elf_load_rsc_table(struct rproc *rproc, 191 + const struct firmware *fw) 192 + { 193 + if (rproc_elf_load_rsc_table(rproc, fw)) 194 + dev_warn(&rproc->dev, "no resource table found for this firmware\n"); 195 + 196 + return 0; 197 + } 198 + 199 + static int stm32_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw) 200 + { 201 + struct device *dev = rproc->dev.parent; 202 + struct device_node *np = dev->of_node; 203 + struct of_phandle_iterator it; 204 + struct rproc_mem_entry *mem; 205 + struct reserved_mem *rmem; 206 + u64 da; 207 + int index = 0; 208 + 209 + /* Register associated reserved memory regions */ 210 + of_phandle_iterator_init(&it, np, "memory-region", NULL, 0); 211 + while (of_phandle_iterator_next(&it) == 0) { 212 + rmem = of_reserved_mem_lookup(it.node); 213 + if (!rmem) { 214 + dev_err(dev, "unable to acquire memory-region\n"); 215 + return -EINVAL; 216 + } 217 + 218 + if (stm32_rproc_pa_to_da(rproc, rmem->base, &da) < 0) { 219 + dev_err(dev, "memory region not valid %pa\n", 220 + &rmem->base); 221 + return -EINVAL; 222 + } 223 + 224 + /* No need to map vdev buffer */ 225 + if (strcmp(it.node->name, "vdev0buffer")) { 226 + /* Register memory region */ 227 + mem = rproc_mem_entry_init(dev, NULL, 228 + (dma_addr_t)rmem->base, 229 + rmem->size, da, 230 + stm32_rproc_mem_alloc, 231 + stm32_rproc_mem_release, 232 + it.node->name); 233 + 234 + if (mem) 235 + rproc_coredump_add_segment(rproc, da, 236 + rmem->size); 237 + } else { 238 + /* Register reserved memory for vdev buffer alloc */ 239 + mem = rproc_of_resm_mem_entry_init(dev, index, 240 + rmem->size, 241 + rmem->base, 242 + it.node->name); 243 + } 244 + 245 + if (!mem) 246 + return -ENOMEM; 247 + 248 + rproc_add_carveout(rproc, mem); 249 + index++; 250 + } 251 + 252 + return stm32_rproc_elf_load_rsc_table(rproc, fw); 253 + } 254 + 255 + static irqreturn_t stm32_rproc_wdg(int irq, void *data) 256 + { 257 + struct rproc *rproc = data; 258 + 259 + rproc_report_crash(rproc, RPROC_WATCHDOG); 260 + 261 + return IRQ_HANDLED; 262 + } 263 + 264 + static void stm32_rproc_mb_callback(struct mbox_client *cl, void *data) 265 + { 266 + struct rproc *rproc = dev_get_drvdata(cl->dev); 267 + struct stm32_mbox *mb = container_of(cl, struct stm32_mbox, client); 268 + 269 + if (rproc_vq_interrupt(rproc, mb->vq_id) == IRQ_NONE) 270 + dev_dbg(&rproc->dev, "no message found in vq%d\n", mb->vq_id); 271 + } 272 + 273 + static void stm32_rproc_free_mbox(struct rproc *rproc) 274 + { 275 + struct stm32_rproc *ddata = rproc->priv; 276 + unsigned int i; 277 + 278 + for (i = 0; i < ARRAY_SIZE(ddata->mb); i++) { 279 + if (ddata->mb[i].chan) 280 + mbox_free_channel(ddata->mb[i].chan); 281 + ddata->mb[i].chan = NULL; 282 + } 283 + } 284 + 285 + static const struct stm32_mbox stm32_rproc_mbox[MBOX_NB_MBX] = { 286 + { 287 + .name = STM32_MBX_VQ0, 288 + .vq_id = 0, 289 + .client = { 290 + .rx_callback = stm32_rproc_mb_callback, 291 + .tx_block = false, 292 + }, 293 + }, 294 + { 295 + .name = STM32_MBX_VQ1, 296 + .vq_id = 1, 297 + .client = { 298 + .rx_callback = stm32_rproc_mb_callback, 299 + .tx_block = false, 300 + }, 301 + }, 302 + { 303 + .name = STM32_MBX_SHUTDOWN, 304 + .vq_id = -1, 305 + .client = { 306 + .tx_block = true, 307 + .tx_done = NULL, 308 + .tx_tout = 500, /* 500 ms time out */ 309 + }, 310 + } 311 + }; 312 + 313 + static void stm32_rproc_request_mbox(struct rproc *rproc) 314 + { 315 + struct stm32_rproc *ddata = rproc->priv; 316 + struct device *dev = &rproc->dev; 317 + unsigned int i; 318 + const unsigned char *name; 319 + struct mbox_client *cl; 320 + 321 + /* Initialise mailbox structure table */ 322 + memcpy(ddata->mb, stm32_rproc_mbox, sizeof(stm32_rproc_mbox)); 323 + 324 + for (i = 0; i < MBOX_NB_MBX; i++) { 325 + name = ddata->mb[i].name; 326 + 327 + cl = &ddata->mb[i].client; 328 + cl->dev = dev->parent; 329 + 330 + ddata->mb[i].chan = mbox_request_channel_byname(cl, name); 331 + if (IS_ERR(ddata->mb[i].chan)) { 332 + dev_warn(dev, "cannot get %s mbox\n", name); 333 + ddata->mb[i].chan = NULL; 334 + } 335 + } 336 + } 337 + 338 + static int stm32_rproc_set_hold_boot(struct rproc *rproc, bool hold) 339 + { 340 + struct stm32_rproc *ddata = rproc->priv; 341 + struct stm32_syscon hold_boot = ddata->hold_boot; 342 + struct arm_smccc_res smc_res; 343 + int val, err; 344 + 345 + val = hold ? HOLD_BOOT : RELEASE_BOOT; 346 + 347 + if (ddata->secured_soc) { 348 + arm_smccc_smc(STM32_SMC_RCC, STM32_SMC_REG_WRITE, 349 + hold_boot.reg, val, 0, 0, 0, 0, &smc_res); 350 + err = smc_res.a0; 351 + } else { 352 + err = regmap_update_bits(hold_boot.map, hold_boot.reg, 353 + hold_boot.mask, val); 354 + } 355 + 356 + if (err) 357 + dev_err(&rproc->dev, "failed to set hold boot\n"); 358 + 359 + return err; 360 + } 361 + 362 + static void stm32_rproc_add_coredump_trace(struct rproc *rproc) 363 + { 364 + struct rproc_debug_trace *trace; 365 + struct rproc_dump_segment *segment; 366 + bool already_added; 367 + 368 + list_for_each_entry(trace, &rproc->traces, node) { 369 + already_added = false; 370 + 371 + list_for_each_entry(segment, &rproc->dump_segments, node) { 372 + if (segment->da == trace->trace_mem.da) { 373 + already_added = true; 374 + break; 375 + } 376 + } 377 + 378 + if (!already_added) 379 + rproc_coredump_add_segment(rproc, trace->trace_mem.da, 380 + trace->trace_mem.len); 381 + } 382 + } 383 + 384 + static int stm32_rproc_start(struct rproc *rproc) 385 + { 386 + int err; 387 + 388 + stm32_rproc_add_coredump_trace(rproc); 389 + 390 + err = stm32_rproc_set_hold_boot(rproc, false); 391 + if (err) 392 + return err; 393 + 394 + return stm32_rproc_set_hold_boot(rproc, true); 395 + } 396 + 397 + static int stm32_rproc_stop(struct rproc *rproc) 398 + { 399 + struct stm32_rproc *ddata = rproc->priv; 400 + int err, dummy_data, idx; 401 + 402 + /* request shutdown of the remote processor */ 403 + if (rproc->state != RPROC_OFFLINE) { 404 + idx = stm32_rproc_mbox_idx(rproc, STM32_MBX_SHUTDOWN); 405 + if (idx >= 0 && ddata->mb[idx].chan) { 406 + /* a dummy data is sent to allow to block on transmit */ 407 + err = mbox_send_message(ddata->mb[idx].chan, 408 + &dummy_data); 409 + if (err < 0) 410 + dev_warn(&rproc->dev, "warning: remote FW shutdown without ack\n"); 411 + } 412 + } 413 + 414 + err = stm32_rproc_set_hold_boot(rproc, true); 415 + if (err) 416 + return err; 417 + 418 + err = reset_control_assert(ddata->rst); 419 + if (err) { 420 + dev_err(&rproc->dev, "failed to assert the reset\n"); 421 + return err; 422 + } 423 + 424 + /* to allow platform Standby power mode, set remote proc Deep Sleep */ 425 + if (ddata->pdds.map) { 426 + err = regmap_update_bits(ddata->pdds.map, ddata->pdds.reg, 427 + ddata->pdds.mask, 1); 428 + if (err) { 429 + dev_err(&rproc->dev, "failed to set pdds\n"); 430 + return err; 431 + } 432 + } 433 + 434 + return 0; 435 + } 436 + 437 + static void stm32_rproc_kick(struct rproc *rproc, int vqid) 438 + { 439 + struct stm32_rproc *ddata = rproc->priv; 440 + unsigned int i; 441 + int err; 442 + 443 + if (WARN_ON(vqid >= MBOX_NB_VQ)) 444 + return; 445 + 446 + for (i = 0; i < MBOX_NB_MBX; i++) { 447 + if (vqid != ddata->mb[i].vq_id) 448 + continue; 449 + if (!ddata->mb[i].chan) 450 + return; 451 + err = mbox_send_message(ddata->mb[i].chan, (void *)(long)vqid); 452 + if (err < 0) 453 + dev_err(&rproc->dev, "%s: failed (%s, err:%d)\n", 454 + __func__, ddata->mb[i].name, err); 455 + return; 456 + } 457 + } 458 + 459 + static struct rproc_ops st_rproc_ops = { 460 + .start = stm32_rproc_start, 461 + .stop = stm32_rproc_stop, 462 + .kick = stm32_rproc_kick, 463 + .load = rproc_elf_load_segments, 464 + .parse_fw = stm32_rproc_parse_fw, 465 + .find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table, 466 + .sanity_check = rproc_elf_sanity_check, 467 + .get_boot_addr = rproc_elf_get_boot_addr, 468 + }; 469 + 470 + static const struct of_device_id stm32_rproc_match[] = { 471 + { .compatible = "st,stm32mp1-m4" }, 472 + {}, 473 + }; 474 + MODULE_DEVICE_TABLE(of, stm32_rproc_match); 475 + 476 + static int stm32_rproc_get_syscon(struct device_node *np, const char *prop, 477 + struct stm32_syscon *syscon) 478 + { 479 + int err = 0; 480 + 481 + syscon->map = syscon_regmap_lookup_by_phandle(np, prop); 482 + if (IS_ERR(syscon->map)) { 483 + err = PTR_ERR(syscon->map); 484 + syscon->map = NULL; 485 + goto out; 486 + } 487 + 488 + err = of_property_read_u32_index(np, prop, 1, &syscon->reg); 489 + if (err) 490 + goto out; 491 + 492 + err = of_property_read_u32_index(np, prop, 2, &syscon->mask); 493 + 494 + out: 495 + return err; 496 + } 497 + 498 + static int stm32_rproc_parse_dt(struct platform_device *pdev) 499 + { 500 + struct device *dev = &pdev->dev; 501 + struct device_node *np = dev->of_node; 502 + struct rproc *rproc = platform_get_drvdata(pdev); 503 + struct stm32_rproc *ddata = rproc->priv; 504 + struct stm32_syscon tz; 505 + unsigned int tzen; 506 + int err, irq; 507 + 508 + irq = platform_get_irq(pdev, 0); 509 + if (irq > 0) { 510 + err = devm_request_irq(dev, irq, stm32_rproc_wdg, 0, 511 + dev_name(dev), rproc); 512 + if (err) { 513 + dev_err(dev, "failed to request wdg irq\n"); 514 + return err; 515 + } 516 + 517 + dev_info(dev, "wdg irq registered\n"); 518 + } 519 + 520 + ddata->rst = devm_reset_control_get_by_index(dev, 0); 521 + if (IS_ERR(ddata->rst)) { 522 + dev_err(dev, "failed to get mcu reset\n"); 523 + return PTR_ERR(ddata->rst); 524 + } 525 + 526 + /* 527 + * if platform is secured the hold boot bit must be written by 528 + * smc call and read normally. 529 + * if not secure the hold boot bit could be read/write normally 530 + */ 531 + err = stm32_rproc_get_syscon(np, "st,syscfg-tz", &tz); 532 + if (err) { 533 + dev_err(dev, "failed to get tz syscfg\n"); 534 + return err; 535 + } 536 + 537 + err = regmap_read(tz.map, tz.reg, &tzen); 538 + if (err) { 539 + dev_err(&rproc->dev, "failed to read tzen\n"); 540 + return err; 541 + } 542 + ddata->secured_soc = tzen & tz.mask; 543 + 544 + err = stm32_rproc_get_syscon(np, "st,syscfg-holdboot", 545 + &ddata->hold_boot); 546 + if (err) { 547 + dev_err(dev, "failed to get hold boot\n"); 548 + return err; 549 + } 550 + 551 + err = stm32_rproc_get_syscon(np, "st,syscfg-pdds", &ddata->pdds); 552 + if (err) 553 + dev_warn(dev, "failed to get pdds\n"); 554 + 555 + rproc->auto_boot = of_property_read_bool(np, "st,auto-boot"); 556 + 557 + return stm32_rproc_of_memory_translations(rproc); 558 + } 559 + 560 + static int stm32_rproc_probe(struct platform_device *pdev) 561 + { 562 + struct device *dev = &pdev->dev; 563 + struct stm32_rproc *ddata; 564 + struct device_node *np = dev->of_node; 565 + struct rproc *rproc; 566 + int ret; 567 + 568 + ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32)); 569 + if (ret) 570 + return ret; 571 + 572 + rproc = rproc_alloc(dev, np->name, &st_rproc_ops, NULL, sizeof(*ddata)); 573 + if (!rproc) 574 + return -ENOMEM; 575 + 576 + rproc->has_iommu = false; 577 + ddata = rproc->priv; 578 + 579 + platform_set_drvdata(pdev, rproc); 580 + 581 + ret = stm32_rproc_parse_dt(pdev); 582 + if (ret) 583 + goto free_rproc; 584 + 585 + stm32_rproc_request_mbox(rproc); 586 + 587 + ret = rproc_add(rproc); 588 + if (ret) 589 + goto free_mb; 590 + 591 + return 0; 592 + 593 + free_mb: 594 + stm32_rproc_free_mbox(rproc); 595 + free_rproc: 596 + rproc_free(rproc); 597 + return ret; 598 + } 599 + 600 + static int stm32_rproc_remove(struct platform_device *pdev) 601 + { 602 + struct rproc *rproc = platform_get_drvdata(pdev); 603 + 604 + if (atomic_read(&rproc->power) > 0) 605 + rproc_shutdown(rproc); 606 + 607 + rproc_del(rproc); 608 + stm32_rproc_free_mbox(rproc); 609 + rproc_free(rproc); 610 + 611 + return 0; 612 + } 613 + 614 + static struct platform_driver stm32_rproc_driver = { 615 + .probe = stm32_rproc_probe, 616 + .remove = stm32_rproc_remove, 617 + .driver = { 618 + .name = "stm32-rproc", 619 + .of_match_table = of_match_ptr(stm32_rproc_match), 620 + }, 621 + }; 622 + module_platform_driver(stm32_rproc_driver); 623 + 624 + MODULE_DESCRIPTION("STM32 Remote Processor Control Driver"); 625 + MODULE_AUTHOR("Ludovic Barre <ludovic.barre@st.com>"); 626 + MODULE_AUTHOR("Fabien Dessenne <fabien.dessenne@st.com>"); 627 + MODULE_LICENSE("GPL v2"); 628 +