668 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * TI K3 Cortex-M4 Remote Processor(s) driver4 *5 * Copyright (C) 2021-2024 Texas Instruments Incorporated - https://www.ti.com/6 * Hari Nagalla <hnagalla@ti.com>7 */8 9#include <linux/io.h>10#include <linux/mailbox_client.h>11#include <linux/module.h>12#include <linux/of_address.h>13#include <linux/of_reserved_mem.h>14#include <linux/platform_device.h>15#include <linux/remoteproc.h>16#include <linux/reset.h>17#include <linux/slab.h>18 19#include "omap_remoteproc.h"20#include "remoteproc_internal.h"21#include "ti_sci_proc.h"22 23#define K3_M4_IRAM_DEV_ADDR 0x0000024#define K3_M4_DRAM_DEV_ADDR 0x3000025 26/**27 * struct k3_m4_rproc_mem - internal memory structure28 * @cpu_addr: MPU virtual address of the memory region29 * @bus_addr: Bus address used to access the memory region30 * @dev_addr: Device address of the memory region from remote processor view31 * @size: Size of the memory region32 */33struct k3_m4_rproc_mem {34 void __iomem *cpu_addr;35 phys_addr_t bus_addr;36 u32 dev_addr;37 size_t size;38};39 40/**41 * struct k3_m4_rproc_mem_data - memory definitions for a remote processor42 * @name: name for this memory entry43 * @dev_addr: device address for the memory entry44 */45struct k3_m4_rproc_mem_data {46 const char *name;47 const u32 dev_addr;48};49 50/**51 * struct k3_m4_rproc - k3 remote processor driver structure52 * @dev: cached device pointer53 * @mem: internal memory regions data54 * @num_mems: number of internal memory regions55 * @rmem: reserved memory regions data56 * @num_rmems: number of reserved memory regions57 * @reset: reset control handle58 * @tsp: TI-SCI processor control handle59 * @ti_sci: TI-SCI handle60 * @ti_sci_id: TI-SCI device identifier61 * @mbox: mailbox channel handle62 * @client: mailbox client to request the mailbox channel63 */64struct k3_m4_rproc {65 struct device *dev;66 struct k3_m4_rproc_mem *mem;67 int num_mems;68 struct k3_m4_rproc_mem *rmem;69 int num_rmems;70 struct reset_control *reset;71 struct ti_sci_proc *tsp;72 const struct ti_sci_handle *ti_sci;73 u32 ti_sci_id;74 struct mbox_chan *mbox;75 struct mbox_client client;76};77 78/**79 * k3_m4_rproc_mbox_callback() - inbound mailbox message handler80 * @client: mailbox client pointer used for requesting the mailbox channel81 * @data: mailbox payload82 *83 * This handler is invoked by the K3 mailbox driver whenever a mailbox84 * message is received. Usually, the mailbox payload simply contains85 * the index of the virtqueue that is kicked by the remote processor,86 * and we let remoteproc core handle it.87 *88 * In addition to virtqueue indices, we also have some out-of-band values89 * that indicate different events. Those values are deliberately very90 * large so they don't coincide with virtqueue indices.91 */92static void k3_m4_rproc_mbox_callback(struct mbox_client *client, void *data)93{94 struct device *dev = client->dev;95 struct rproc *rproc = dev_get_drvdata(dev);96 u32 msg = (u32)(uintptr_t)(data);97 98 dev_dbg(dev, "mbox msg: 0x%x\n", msg);99 100 switch (msg) {101 case RP_MBOX_CRASH:102 /*103 * remoteproc detected an exception, but error recovery is not104 * supported. So, just log this for now105 */106 dev_err(dev, "K3 rproc %s crashed\n", rproc->name);107 break;108 case RP_MBOX_ECHO_REPLY:109 dev_info(dev, "received echo reply from %s\n", rproc->name);110 break;111 default:112 /* silently handle all other valid messages */113 if (msg >= RP_MBOX_READY && msg < RP_MBOX_END_MSG)114 return;115 if (msg > rproc->max_notifyid) {116 dev_dbg(dev, "dropping unknown message 0x%x", msg);117 return;118 }119 /* msg contains the index of the triggered vring */120 if (rproc_vq_interrupt(rproc, msg) == IRQ_NONE)121 dev_dbg(dev, "no message was found in vqid %d\n", msg);122 }123}124 125/*126 * Kick the remote processor to notify about pending unprocessed messages.127 * The vqid usage is not used and is inconsequential, as the kick is performed128 * through a simulated GPIO (a bit in an IPC interrupt-triggering register),129 * the remote processor is expected to process both its Tx and Rx virtqueues.130 */131static void k3_m4_rproc_kick(struct rproc *rproc, int vqid)132{133 struct k3_m4_rproc *kproc = rproc->priv;134 struct device *dev = kproc->dev;135 u32 msg = (u32)vqid;136 int ret;137 138 /*139 * Send the index of the triggered virtqueue in the mailbox payload.140 * NOTE: msg is cast to uintptr_t to prevent compiler warnings when141 * void* is 64bit. It is safely cast back to u32 in the mailbox driver.142 */143 ret = mbox_send_message(kproc->mbox, (void *)(uintptr_t)msg);144 if (ret < 0)145 dev_err(dev, "failed to send mailbox message, status = %d\n",146 ret);147}148 149static int k3_m4_rproc_ping_mbox(struct k3_m4_rproc *kproc)150{151 struct device *dev = kproc->dev;152 int ret;153 154 /*155 * Ping the remote processor, this is only for sanity-sake for now;156 * there is no functional effect whatsoever.157 *158 * Note that the reply will _not_ arrive immediately: this message159 * will wait in the mailbox fifo until the remote processor is booted.160 */161 ret = mbox_send_message(kproc->mbox, (void *)RP_MBOX_ECHO_REQUEST);162 if (ret < 0) {163 dev_err(dev, "mbox_send_message failed: %d\n", ret);164 return ret;165 }166 167 return 0;168}169 170/*171 * The M4 cores have a local reset that affects only the CPU, and a172 * generic module reset that powers on the device and allows the internal173 * memories to be accessed while the local reset is asserted. This function is174 * used to release the global reset on remote cores to allow loading into the175 * internal RAMs. The .prepare() ops is invoked by remoteproc core before any176 * firmware loading, and is followed by the .start() ops after loading to177 * actually let the remote cores to run.178 */179static int k3_m4_rproc_prepare(struct rproc *rproc)180{181 struct k3_m4_rproc *kproc = rproc->priv;182 struct device *dev = kproc->dev;183 int ret;184 185 /* If the core is running already no need to deassert the module reset */186 if (rproc->state == RPROC_DETACHED)187 return 0;188 189 /*190 * Ensure the local reset is asserted so the core doesn't191 * execute bogus code when the module reset is released.192 */193 ret = reset_control_assert(kproc->reset);194 if (ret) {195 dev_err(dev, "could not assert local reset\n");196 return ret;197 }198 199 ret = reset_control_status(kproc->reset);200 if (ret <= 0) {201 dev_err(dev, "local reset still not asserted\n");202 return ret;203 }204 205 ret = kproc->ti_sci->ops.dev_ops.get_device(kproc->ti_sci,206 kproc->ti_sci_id);207 if (ret) {208 dev_err(dev, "could not deassert module-reset for internal RAM loading\n");209 return ret;210 }211 212 return 0;213}214 215/*216 * This function implements the .unprepare() ops and performs the complimentary217 * operations to that of the .prepare() ops. The function is used to assert the218 * global reset on applicable cores. This completes the second portion of219 * powering down the remote core. The cores themselves are only halted in the220 * .stop() callback through the local reset, and the .unprepare() ops is invoked221 * by the remoteproc core after the remoteproc is stopped to balance the global222 * reset.223 */224static int k3_m4_rproc_unprepare(struct rproc *rproc)225{226 struct k3_m4_rproc *kproc = rproc->priv;227 struct device *dev = kproc->dev;228 int ret;229 230 /* If the core is going to be detached do not assert the module reset */231 if (rproc->state == RPROC_ATTACHED)232 return 0;233 234 ret = kproc->ti_sci->ops.dev_ops.put_device(kproc->ti_sci,235 kproc->ti_sci_id);236 if (ret) {237 dev_err(dev, "module-reset assert failed\n");238 return ret;239 }240 241 return 0;242}243 244/*245 * This function implements the .get_loaded_rsc_table() callback and is used246 * to provide the resource table for a booted remote processor in IPC-only247 * mode. The remote processor firmwares follow a design-by-contract approach248 * and are expected to have the resource table at the base of the DDR region249 * reserved for firmware usage. This provides flexibility for the remote250 * processor to be booted by different bootloaders that may or may not have the251 * ability to publish the resource table address and size through a DT252 * property.253 */254static struct resource_table *k3_m4_get_loaded_rsc_table(struct rproc *rproc,255 size_t *rsc_table_sz)256{257 struct k3_m4_rproc *kproc = rproc->priv;258 struct device *dev = kproc->dev;259 260 if (!kproc->rmem[0].cpu_addr) {261 dev_err(dev, "memory-region #1 does not exist, loaded rsc table can't be found");262 return ERR_PTR(-ENOMEM);263 }264 265 /*266 * NOTE: The resource table size is currently hard-coded to a maximum267 * of 256 bytes. The most common resource table usage for K3 firmwares268 * is to only have the vdev resource entry and an optional trace entry.269 * The exact size could be computed based on resource table address, but270 * the hard-coded value suffices to support the IPC-only mode.271 */272 *rsc_table_sz = 256;273 return (__force struct resource_table *)kproc->rmem[0].cpu_addr;274}275 276/*277 * Custom function to translate a remote processor device address (internal278 * RAMs only) to a kernel virtual address. The remote processors can access279 * their RAMs at either an internal address visible only from a remote280 * processor, or at the SoC-level bus address. Both these addresses need to be281 * looked through for translation. The translated addresses can be used either282 * by the remoteproc core for loading (when using kernel remoteproc loader), or283 * by any rpmsg bus drivers.284 */285static void *k3_m4_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)286{287 struct k3_m4_rproc *kproc = rproc->priv;288 void __iomem *va = NULL;289 phys_addr_t bus_addr;290 u32 dev_addr, offset;291 size_t size;292 int i;293 294 if (len == 0)295 return NULL;296 297 for (i = 0; i < kproc->num_mems; i++) {298 bus_addr = kproc->mem[i].bus_addr;299 dev_addr = kproc->mem[i].dev_addr;300 size = kproc->mem[i].size;301 302 /* handle M4-view addresses */303 if (da >= dev_addr && ((da + len) <= (dev_addr + size))) {304 offset = da - dev_addr;305 va = kproc->mem[i].cpu_addr + offset;306 return (__force void *)va;307 }308 309 /* handle SoC-view addresses */310 if (da >= bus_addr && ((da + len) <= (bus_addr + size))) {311 offset = da - bus_addr;312 va = kproc->mem[i].cpu_addr + offset;313 return (__force void *)va;314 }315 }316 317 /* handle static DDR reserved memory regions */318 for (i = 0; i < kproc->num_rmems; i++) {319 dev_addr = kproc->rmem[i].dev_addr;320 size = kproc->rmem[i].size;321 322 if (da >= dev_addr && ((da + len) <= (dev_addr + size))) {323 offset = da - dev_addr;324 va = kproc->rmem[i].cpu_addr + offset;325 return (__force void *)va;326 }327 }328 329 return NULL;330}331 332static int k3_m4_rproc_of_get_memories(struct platform_device *pdev,333 struct k3_m4_rproc *kproc)334{335 static const char * const mem_names[] = { "iram", "dram" };336 static const u32 mem_addrs[] = { K3_M4_IRAM_DEV_ADDR, K3_M4_DRAM_DEV_ADDR };337 struct device *dev = &pdev->dev;338 struct resource *res;339 int num_mems;340 int i;341 342 num_mems = ARRAY_SIZE(mem_names);343 kproc->mem = devm_kcalloc(kproc->dev, num_mems,344 sizeof(*kproc->mem), GFP_KERNEL);345 if (!kproc->mem)346 return -ENOMEM;347 348 for (i = 0; i < num_mems; i++) {349 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,350 mem_names[i]);351 if (!res) {352 dev_err(dev, "found no memory resource for %s\n",353 mem_names[i]);354 return -EINVAL;355 }356 if (!devm_request_mem_region(dev, res->start,357 resource_size(res),358 dev_name(dev))) {359 dev_err(dev, "could not request %s region for resource\n",360 mem_names[i]);361 return -EBUSY;362 }363 364 kproc->mem[i].cpu_addr = devm_ioremap_wc(dev, res->start,365 resource_size(res));366 if (!kproc->mem[i].cpu_addr) {367 dev_err(dev, "failed to map %s memory\n",368 mem_names[i]);369 return -ENOMEM;370 }371 kproc->mem[i].bus_addr = res->start;372 kproc->mem[i].dev_addr = mem_addrs[i];373 kproc->mem[i].size = resource_size(res);374 375 dev_dbg(dev, "memory %8s: bus addr %pa size 0x%zx va %pK da 0x%x\n",376 mem_names[i], &kproc->mem[i].bus_addr,377 kproc->mem[i].size, kproc->mem[i].cpu_addr,378 kproc->mem[i].dev_addr);379 }380 kproc->num_mems = num_mems;381 382 return 0;383}384 385static void k3_m4_rproc_dev_mem_release(void *data)386{387 struct device *dev = data;388 389 of_reserved_mem_device_release(dev);390}391 392static int k3_m4_reserved_mem_init(struct k3_m4_rproc *kproc)393{394 struct device *dev = kproc->dev;395 struct device_node *np = dev->of_node;396 struct device_node *rmem_np;397 struct reserved_mem *rmem;398 int num_rmems;399 int ret, i;400 401 num_rmems = of_property_count_elems_of_size(np, "memory-region",402 sizeof(phandle));403 if (num_rmems < 0) {404 dev_err(dev, "device does not reserved memory regions (%d)\n",405 num_rmems);406 return -EINVAL;407 }408 if (num_rmems < 2) {409 dev_err(dev, "device needs at least two memory regions to be defined, num = %d\n",410 num_rmems);411 return -EINVAL;412 }413 414 /* use reserved memory region 0 for vring DMA allocations */415 ret = of_reserved_mem_device_init_by_idx(dev, np, 0);416 if (ret) {417 dev_err(dev, "device cannot initialize DMA pool (%d)\n", ret);418 return ret;419 }420 ret = devm_add_action_or_reset(dev, k3_m4_rproc_dev_mem_release, dev);421 if (ret)422 return ret;423 424 num_rmems--;425 kproc->rmem = devm_kcalloc(dev, num_rmems, sizeof(*kproc->rmem), GFP_KERNEL);426 if (!kproc->rmem)427 return -ENOMEM;428 429 /* use remaining reserved memory regions for static carveouts */430 for (i = 0; i < num_rmems; i++) {431 rmem_np = of_parse_phandle(np, "memory-region", i + 1);432 if (!rmem_np)433 return -EINVAL;434 435 rmem = of_reserved_mem_lookup(rmem_np);436 if (!rmem) {437 of_node_put(rmem_np);438 return -EINVAL;439 }440 of_node_put(rmem_np);441 442 kproc->rmem[i].bus_addr = rmem->base;443 /* 64-bit address regions currently not supported */444 kproc->rmem[i].dev_addr = (u32)rmem->base;445 kproc->rmem[i].size = rmem->size;446 kproc->rmem[i].cpu_addr = devm_ioremap_wc(dev, rmem->base, rmem->size);447 if (!kproc->rmem[i].cpu_addr) {448 dev_err(dev, "failed to map reserved memory#%d at %pa of size %pa\n",449 i + 1, &rmem->base, &rmem->size);450 return -ENOMEM;451 }452 453 dev_dbg(dev, "reserved memory%d: bus addr %pa size 0x%zx va %pK da 0x%x\n",454 i + 1, &kproc->rmem[i].bus_addr,455 kproc->rmem[i].size, kproc->rmem[i].cpu_addr,456 kproc->rmem[i].dev_addr);457 }458 kproc->num_rmems = num_rmems;459 460 return 0;461}462 463static void k3_m4_release_tsp(void *data)464{465 struct ti_sci_proc *tsp = data;466 467 ti_sci_proc_release(tsp);468}469 470/*471 * Power up the M4 remote processor.472 *473 * This function will be invoked only after the firmware for this rproc474 * was loaded, parsed successfully, and all of its resource requirements475 * were met. This callback is invoked only in remoteproc mode.476 */477static int k3_m4_rproc_start(struct rproc *rproc)478{479 struct k3_m4_rproc *kproc = rproc->priv;480 struct device *dev = kproc->dev;481 int ret;482 483 ret = k3_m4_rproc_ping_mbox(kproc);484 if (ret)485 return ret;486 487 ret = reset_control_deassert(kproc->reset);488 if (ret) {489 dev_err(dev, "local-reset deassert failed, ret = %d\n", ret);490 return ret;491 }492 493 return 0;494}495 496/*497 * Stop the M4 remote processor.498 *499 * This function puts the M4 processor into reset, and finishes processing500 * of any pending messages. This callback is invoked only in remoteproc mode.501 */502static int k3_m4_rproc_stop(struct rproc *rproc)503{504 struct k3_m4_rproc *kproc = rproc->priv;505 struct device *dev = kproc->dev;506 int ret;507 508 ret = reset_control_assert(kproc->reset);509 if (ret) {510 dev_err(dev, "local-reset assert failed, ret = %d\n", ret);511 return ret;512 }513 514 return 0;515}516 517/*518 * Attach to a running M4 remote processor (IPC-only mode)519 *520 * The remote processor is already booted, so there is no need to issue any521 * TI-SCI commands to boot the M4 core. This callback is used only in IPC-only522 * mode.523 */524static int k3_m4_rproc_attach(struct rproc *rproc)525{526 struct k3_m4_rproc *kproc = rproc->priv;527 int ret;528 529 ret = k3_m4_rproc_ping_mbox(kproc);530 if (ret)531 return ret;532 533 return 0;534}535 536/*537 * Detach from a running M4 remote processor (IPC-only mode)538 *539 * This rproc detach callback performs the opposite operation to attach540 * callback, the M4 core is not stopped and will be left to continue to541 * run its booted firmware. This callback is invoked only in IPC-only mode.542 */543static int k3_m4_rproc_detach(struct rproc *rproc)544{545 return 0;546}547 548static const struct rproc_ops k3_m4_rproc_ops = {549 .prepare = k3_m4_rproc_prepare,550 .unprepare = k3_m4_rproc_unprepare,551 .start = k3_m4_rproc_start,552 .stop = k3_m4_rproc_stop,553 .attach = k3_m4_rproc_attach,554 .detach = k3_m4_rproc_detach,555 .kick = k3_m4_rproc_kick,556 .da_to_va = k3_m4_rproc_da_to_va,557 .get_loaded_rsc_table = k3_m4_get_loaded_rsc_table,558};559 560static int k3_m4_rproc_probe(struct platform_device *pdev)561{562 struct device *dev = &pdev->dev;563 struct k3_m4_rproc *kproc;564 struct rproc *rproc;565 const char *fw_name;566 bool r_state = false;567 bool p_state = false;568 int ret;569 570 ret = rproc_of_parse_firmware(dev, 0, &fw_name);571 if (ret)572 return dev_err_probe(dev, ret, "failed to parse firmware-name property\n");573 574 rproc = devm_rproc_alloc(dev, dev_name(dev), &k3_m4_rproc_ops, fw_name,575 sizeof(*kproc));576 if (!rproc)577 return -ENOMEM;578 579 rproc->has_iommu = false;580 rproc->recovery_disabled = true;581 kproc = rproc->priv;582 kproc->dev = dev;583 platform_set_drvdata(pdev, rproc);584 585 kproc->ti_sci = devm_ti_sci_get_by_phandle(dev, "ti,sci");586 if (IS_ERR(kproc->ti_sci))587 return dev_err_probe(dev, PTR_ERR(kproc->ti_sci),588 "failed to get ti-sci handle\n");589 590 ret = of_property_read_u32(dev->of_node, "ti,sci-dev-id", &kproc->ti_sci_id);591 if (ret)592 return dev_err_probe(dev, ret, "missing 'ti,sci-dev-id' property\n");593 594 kproc->reset = devm_reset_control_get_exclusive(dev, NULL);595 if (IS_ERR(kproc->reset))596 return dev_err_probe(dev, PTR_ERR(kproc->reset), "failed to get reset\n");597 598 kproc->tsp = ti_sci_proc_of_get_tsp(dev, kproc->ti_sci);599 if (IS_ERR(kproc->tsp))600 return dev_err_probe(dev, PTR_ERR(kproc->tsp),601 "failed to construct ti-sci proc control\n");602 603 ret = ti_sci_proc_request(kproc->tsp);604 if (ret < 0)605 return dev_err_probe(dev, ret, "ti_sci_proc_request failed\n");606 ret = devm_add_action_or_reset(dev, k3_m4_release_tsp, kproc->tsp);607 if (ret)608 return ret;609 610 ret = k3_m4_rproc_of_get_memories(pdev, kproc);611 if (ret)612 return ret;613 614 ret = k3_m4_reserved_mem_init(kproc);615 if (ret)616 return dev_err_probe(dev, ret, "reserved memory init failed\n");617 618 ret = kproc->ti_sci->ops.dev_ops.is_on(kproc->ti_sci, kproc->ti_sci_id,619 &r_state, &p_state);620 if (ret)621 return dev_err_probe(dev, ret,622 "failed to get initial state, mode cannot be determined\n");623 624 /* configure devices for either remoteproc or IPC-only mode */625 if (p_state) {626 rproc->state = RPROC_DETACHED;627 dev_info(dev, "configured M4F for IPC-only mode\n");628 } else {629 dev_info(dev, "configured M4F for remoteproc mode\n");630 }631 632 kproc->client.dev = dev;633 kproc->client.tx_done = NULL;634 kproc->client.rx_callback = k3_m4_rproc_mbox_callback;635 kproc->client.tx_block = false;636 kproc->client.knows_txdone = false;637 kproc->mbox = mbox_request_channel(&kproc->client, 0);638 if (IS_ERR(kproc->mbox))639 return dev_err_probe(dev, PTR_ERR(kproc->mbox),640 "mbox_request_channel failed\n");641 642 ret = devm_rproc_add(dev, rproc);643 if (ret)644 return dev_err_probe(dev, ret,645 "failed to register device with remoteproc core\n");646 647 return 0;648}649 650static const struct of_device_id k3_m4_of_match[] = {651 { .compatible = "ti,am64-m4fss", },652 { /* sentinel */ },653};654MODULE_DEVICE_TABLE(of, k3_m4_of_match);655 656static struct platform_driver k3_m4_rproc_driver = {657 .probe = k3_m4_rproc_probe,658 .driver = {659 .name = "k3-m4-rproc",660 .of_match_table = k3_m4_of_match,661 },662};663module_platform_driver(k3_m4_rproc_driver);664 665MODULE_AUTHOR("Hari Nagalla <hnagalla@ti.com>");666MODULE_DESCRIPTION("TI K3 M4 Remoteproc driver");667MODULE_LICENSE("GPL");668